Skip to content

Commit

Permalink
Faster writing due to a new writing system.
Browse files Browse the repository at this point in the history
When using the json* method, a stream is used to write the data.  Writing of json forms will likely benefit from not using streams in the future.
  • Loading branch information
madnificent committed Aug 25, 2010
1 parent 5fe3c86 commit 7fb6973
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 8 deletions.
3 changes: 2 additions & 1 deletion packages.lisp
Expand Up @@ -5,7 +5,8 @@
:build-key-container
:parse-with-container)
;; writing
(:export :to-json)
(:export :to-json
:to-json*)
;; editing
(:export :keywords
:val
Expand Down
80 changes: 73 additions & 7 deletions writer.lisp
@@ -1,29 +1,95 @@
(in-package :jsown)

(declaim (optimize (speed 0) (debug 3) (safety 3)))
(declaim (optimize (speed 3) (debug 3) (safety 0)))

;;;;;;;;;;;;;;;;;;
;; generic writing
(defgeneric to-json (object)
(:documentation "Writes the given object to json"))
(:documentation "Writes the given object to json in a generic way."))

(defmethod to-json ((string string))
(with-output-to-string (stream)
(write string :stream stream)))
(write-string string stream)))
(defmethod to-json ((number number))
(with-output-to-string (stream)
(write number :stream stream)))
(write number :stream stream :pretty nil)))
(defmethod to-json ((ratio ratio))
(to-json (coerce ratio 'float)))

(defmethod to-json ((list list))
(if (eq (car list) :obj)
(object-to-json (cdr list))
(list-to-json list)))
(let ((*print-pretty* nil)) ;; *pretty-print* makes printing very slow, internal json objects needn't have this
(if (eq (car list) :obj)
(object-to-json (cdr list))
(list-to-json list))))

(defun object-to-json (list)
(format nil "{~{~{~A:~A~}~^,~}}"
(loop for item in list collect
(list (to-json (car item))
(to-json (cdr item))))))

(defun list-to-json (list)
(format nil "[~{~A~^,~}]"
(mapcar #'to-json list)))

;;;;;;;;;;;;;;;;;
;; speedy writing
(defun list-is-object-p (list)
(declare (type (or cons nil) list))
(and (consp list)
(eq (car list) :obj)))

(defun to-json* (object)
"Converts an object in internal jsown representation to a string containing the json representation"
(let ((*print-pretty* nil))
(with-output-to-string (output)
(write-object-to-stream object output))))

(defun write-number* (object output)
(declare (type number object)
(type stream output))
(write object :stream output))

(defun write-string* (object output)
(declare (type string object)
(type stream output))
(write-string object output))

(declaim (inline write-number* write-string*))

(defun write-object-to-stream (object output)
(declare (type stream output))
(typecase object
(ratio (write (coerce object 'float) :stream output))
(number (write-number* object output))
(string (write-string* object output))
(T (if (list-is-object-p object)
(if (null (cdr object))
"{}"
(progn
(format output "{")
(write-string* (caadr object) output)
(format output ":")
(write-object-to-stream (cdadr object) output)
(loop
for curr-obj in (cdr object)
do (progn
(let ((k (car curr-obj))
(v (cdr curr-obj)))
(declare (type string k))
(format output ",")
(write-string* k output)
(format output ":")
(write-object-to-stream v output))))
(format output "}")))
(progn
(if (null (cdr object))
(format output "[]")
(progn
(format output "[")
(write-object-to-stream (first object) output)
(loop for item in (rest object)
do (progn
(format output ",")
(write-object-to-stream item output)))
(format output "]"))))))))

0 comments on commit 7fb6973

Please sign in to comment.