changeset 698: | 96958d3eb5b0 |
parent: | 5540a3e32ba1 |
author: | Richard Westhaver <ellis@rwest.io> |
date: | Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: | -rw-r--r-- |
description: | fixes |
122
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
1 | ;;; lib/dat/json.lisp --- JSON format |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
2 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
3 | ;; JSON parser generator |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
4 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
5 | ;; There are quite a few json libraries in the CL ecosystem. This |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
6 | ;; particular implementation is based on the JSON package here: |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
7 | ;; https://github.com/massung/json |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
8 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
9 | ;; It's object-based (like CL-JSON) instead of using a |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
10 | ;; parser-generator. |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
11 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
12 | ;;; Code: |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
13 | (in-package :dat/json) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
14 | |
439
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
15 | (defvar *allow-json-trailing-commas* nil |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
16 | "When non-nil, arrange for our json readers to allow trailing |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
17 | commas. This binding does not affect writers. |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
18 | |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
19 | Trailing commas in json lists and objects is a common source of frustration |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
20 | since they're not allowed in the spec. This is easily forgotten when |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
21 | generating json from a scripting language without native json support." |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
22 | ) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
23 | |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
24 | (defun json-trailing-commas-p () *allow-json-trailing-commas*) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
25 | |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
26 | (defsetf json-trailing-commas-p () (val) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
27 | `(setq *allow-json-trailing-commas* ,val)) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
28 | |
122
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
29 | (defclass json-object () |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
30 | ((members :initform nil |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
31 | :initarg :members |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
32 | :accessor json-object-members)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
33 | (:documentation "An associative list of key/value pairs.")) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
34 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
35 | (defmethod print-object ((obj json-object) stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
36 | "Output a JSON object to a stream in readable form." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
37 | (print-unreadable-object (obj stream :type t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
38 | (let ((*print-level* 1)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
39 | (json-encode obj stream)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
40 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
41 | (defun json-getf (object key &optional value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
42 | "Find an member's value in a JSON object." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
43 | (let ((place (assoc key (json-object-members object) :test 'string=))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
44 | (if (null place) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
45 | value |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
46 | (values (second place) t)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
47 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
48 | (defun json-setf (object key value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
49 | "Assign a value to a key in a JSON object." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
50 | (let ((place (assoc key (json-object-members object) :test 'string=))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
51 | (prog1 value |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
52 | (if (null place) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
53 | (let ((k (if (stringp key) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
54 | key |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
55 | (princ-to-string key)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
56 | (push (list k value) (json-object-members object))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
57 | (rplacd place (list value)))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
58 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
59 | (defsetf json-getf json-setf) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
60 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
61 | (defun json-decode (string &key (start 0) end) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
62 | "Convert a JSON string into a Lisp object." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
63 | (with-input-from-string (stream string :start start :end end) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
64 | (values (json-read stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
65 | (file-position stream)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
66 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
67 | (defmethod deserialize ((obj string) (format (eql :json)) &key (start 0) end) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
68 | (declare (ignore format)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
69 | (json-decode obj :start start :end end)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
70 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
71 | (defun json-encode (value &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
72 | "Encodes a Lisp value into a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
73 | (json-write value stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
74 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
75 | (defmethod serialize (obj (format (eql :json)) &key stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
76 | (declare (ignore format)) |
225 | 77 | (if stream |
78 | (json-encode obj stream) |
|
79 | (with-output-to-string (s) |
|
80 | (json-encode obj s) |
|
81 | s))) |
|
122
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
82 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
83 | (defun json-enable-reader-macro () |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
84 | "Set the #{ dispatch macro character for reading JSON objects." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
85 | (flet ((json-object-reader (stream char n) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
86 | (declare (ignorable char n)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
87 | (let ((xs (read-delimited-list #\} stream t))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
88 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
89 | for key = (pop xs) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
90 | for value = (pop xs) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
91 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
92 | ;; stop when nothing is left |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
93 | unless (or xs key value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
94 | return (make-instance 'json-object :members pairs) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
95 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
96 | ;; build associative list of key/value pairs |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
97 | collect (list (princ-to-string key) value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
98 | into pairs)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
99 | (set-dispatch-macro-character #\# #\{ #'json-object-reader) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
100 | (set-macro-character #\} (get-macro-character #\) nil)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
101 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
102 | (defun json-read (stream &optional (eof-error-p t) eof-value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
103 | "Read a JSON object from a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
104 | (let ((c (peek-char t stream eof-error-p :eof))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
105 | (case c |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
106 | (:eof eof-value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
107 | ;; constants, objects, lists, and strings |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
108 | (#\t (json-read-true stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
109 | (#\f (json-read-false stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
110 | (#\n (json-read-null stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
111 | (#\{ (json-read-object stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
112 | (#\[ (json-read-list stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
113 | (#\" (json-read-string stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
114 | ;; must be a number |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
115 | (otherwise (json-read-number stream))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
116 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
117 | (defun json-peek-char (stream expected &key skip-ws) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
118 | "Peek at the next character or token and optionally error if unexpected." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
119 | (declare (optimize (speed 3) (debug 0))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
120 | (when (equal (peek-char skip-ws stream) expected) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
121 | (read-char stream))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
122 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
123 | (defun json-read-char (stream expected &key skip-ws) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
124 | "Read the next, expected character in the stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
125 | (declare (optimize (speed 3) (debug 0))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
126 | (if (json-peek-char stream expected :skip-ws skip-ws) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
127 | t |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
128 | (error "JSON error: unexpected ~s" (read-char stream)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
129 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
130 | (defun json-read-true (stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
131 | "Read true from a JSON stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
132 | (json-read-char stream #\t :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
133 | (json-read-char stream #\r) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
134 | (json-read-char stream #\u) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
135 | (json-read-char stream #\e)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
136 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
137 | (defun json-read-false (stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
138 | "Read false from a JSON stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
139 | (prog1 nil |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
140 | (json-read-char stream #\f :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
141 | (json-read-char stream #\a) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
142 | (json-read-char stream #\l) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
143 | (json-read-char stream #\s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
144 | (json-read-char stream #\e))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
145 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
146 | (defun json-read-null (stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
147 | "Read null from a JSON stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
148 | (prog1 nil |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
149 | (json-read-char stream #\n :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
150 | (json-read-char stream #\u) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
151 | (json-read-char stream #\l) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
152 | (json-read-char stream #\l))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
153 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
154 | (defun json-read-number (stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
155 | "Read a number from a JSON stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
156 | (declare (optimize (speed 3) (debug 0))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
157 | (let ((s (with-output-to-string (s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
158 | (when (equal (peek-char t stream) #\-) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
159 | (write-char (read-char stream) s)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
160 | ;; read base-10 digits, fraction, and exponent |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
161 | (labels ((read-digits () |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
162 | (let ((c (read-char stream))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
163 | (unless (digit-char-p c) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
164 | (error "JSON error: unexpected ~s" c)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
165 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
166 | ;; write the digits |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
167 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
168 | (write-char c s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
169 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
170 | ;; next digit, test for eof |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
171 | (unless (setf c (read-char stream nil)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
172 | (return)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
173 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
174 | ;; ensure digit |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
175 | (unless (digit-char-p c) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
176 | (return (unread-char c stream)))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
177 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
178 | ;; fractional component |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
179 | (read-fraction () |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
180 | (when (equal (peek-char nil stream nil) #\.) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
181 | (write-char (read-char stream) s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
182 | (read-digits))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
183 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
184 | ;; exponent |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
185 | (read-exponent () |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
186 | (when (equalp (peek-char nil stream nil) #\e) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
187 | (write-char (read-char stream) s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
188 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
189 | ;; optional sign |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
190 | (case (peek-char nil stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
191 | (#\- (write-char (read-char stream) s)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
192 | (#\+ (write-char (read-char stream) s))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
193 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
194 | ;; exponent |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
195 | (read-digits)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
196 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
197 | ;; read each component; numbers beginning with 0 are a special case |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
198 | (if (equalp (peek-char nil stream) #\0) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
199 | (write-char (read-char stream) s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
200 | (read-digits)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
201 | (read-fraction) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
202 | (read-exponent))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
203 | (prog1 |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
204 | (read-from-string s)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
205 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
206 | (defun json-read-string (stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
207 | "Read a string from a JSON stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
208 | (declare (optimize (speed 3) (debug 0))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
209 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
210 | ;; read the expected quote |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
211 | (json-read-char stream #\" :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
212 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
213 | ;; read into an output buffer |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
214 | (with-output-to-string (s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
215 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
216 | for c = (read-char stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
217 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
218 | ;; stop at closing quote |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
219 | until (char= c #\") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
220 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
221 | ;; write character to output |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
222 | do (if (char/= c #\\) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
223 | (write-char c s) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
224 | (let ((c (case (read-char stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
225 | (#\n #\newline) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
226 | (#\t #\tab) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
227 | (#\f #\formfeed) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
228 | (#\b #\backspace) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
229 | (#\r #\return) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
230 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
231 | ;; read unicode character |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
232 | (#\u (let ((x1 (digit-char-p (read-char stream) 16)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
233 | (x2 (digit-char-p (read-char stream) 16)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
234 | (x3 (digit-char-p (read-char stream) 16)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
235 | (x4 (digit-char-p (read-char stream) 16))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
236 | (code-char (logior (ash x1 12) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
237 | (ash x2 8) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
238 | (ash x3 4) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
239 | (ash x4 0))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
240 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
241 | ;; verbatim character |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
242 | (otherwise c)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
243 | (write-char c s)))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
244 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
245 | (defun json-read-list (stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
246 | "Read a list of JSON values." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
247 | (declare (optimize (speed 3) (debug 0))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
248 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
249 | ;; read the expected open bracket |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
250 | (json-read-char stream #\[ :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
251 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
252 | ;; check for an empty list |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
253 | (if (json-peek-char stream #\] :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
254 | nil |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
255 | (loop |
439
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
256 | for x = (json-read stream) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
257 | collect x |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
258 | into xs |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
259 | ;; check for another element |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
260 | while (and (json-peek-char stream #\, :skip-ws t) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
261 | (unless (and (json-trailing-commas-p) (equal #\] (peek-char t stream))) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
262 | t)) |
122
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
263 | ;; return the final list |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
264 | finally (return (prog1 xs |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
265 | (json-read-char stream #\] :skip-ws t)))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
266 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
267 | (defun json-read-object (stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
268 | "Read an associative list of key/value pairs into a JSON object." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
269 | (declare (optimize (speed 3) (debug 0))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
270 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
271 | ;; read the expected open brace |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
272 | (json-read-char stream #\{ :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
273 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
274 | ;; check for an empty object |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
275 | (if (json-peek-char stream #\} :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
276 | (make-instance 'json-object) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
277 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
278 | for key = (json-read-string stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
279 | for value = (progn |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
280 | (json-read-char stream #\: :skip-ws t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
281 | (json-read stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
282 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
283 | ;; build the associative list of members |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
284 | collect (list key value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
285 | into xs |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
286 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
287 | ;; check for another element |
439
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
288 | while (and (json-peek-char stream #\, :skip-ws t) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
289 | (unless (and (json-trailing-commas-p) (equal #\} (peek-char t stream))) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
290 | t)) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
291 | ;; return the final list |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
292 | finally (return (prog1 (make-instance 'json-object :members xs) |
ea4f008ad13f
packy work, added json-trailing-whitespace-p variable for json readers
Richard Westhaver <ellis@rwest.io>
parents:
395
diff
changeset
|
293 | (json-read-char stream #\} :skip-ws t)))))) |
122
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
294 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
295 | (defmethod json-write ((value (eql t)) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
296 | "Encode the true value." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
297 | (declare (ignore value)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
298 | (format stream "~<true~>")) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
299 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
300 | (defmethod json-write ((value (eql nil)) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
301 | "Encode the null constant." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
302 | (declare (ignore value)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
303 | (format stream "~<null~>")) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
304 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
305 | (defmethod json-write ((value symbol) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
306 | "Encode a symbol to a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
307 | (json-write (symbol-name value) stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
308 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
309 | (defmethod json-write ((value number) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
310 | "Encode a number to a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
311 | (format stream "~<~a~>" value)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
312 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
313 | (defmethod json-write ((value ratio) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
314 | "Encode a ratio to a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
315 | (format stream "~<~a~>" (float value))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
316 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
317 | (defmethod json-write ((value string) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
318 | "Encode a string as a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
319 | (flet ((encode-char (c) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
320 | (cond |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
321 | ((char= c #\\) "\\\\") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
322 | ((char= c #\") "\\\"") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
323 | ((char= c #\newline) "\\n") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
324 | ((char= c #\tab) "\\t") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
325 | ((char= c #\formfeed) "\\f") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
326 | ((char= c #\backspace) "\\b") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
327 | ((char= c #\return) "\\r") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
328 | ((char> c #\~) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
329 | (format nil "\\u~16,4,'0r" (char-code c))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
330 | (t |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
331 | (string c))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
332 | (format stream "~<\"~{~a~}\"~>" (map 'list #'encode-char value)))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
333 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
334 | (defmethod json-write ((value pathname) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
335 | "Encode a pathname as a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
336 | (json-write (namestring value) stream)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
337 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
338 | (defmethod json-write ((value vector) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
339 | "Encode an array to a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
340 | (let ((*print-pretty* t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
341 | (*print-length* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
342 | (*print-lines* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
343 | (*print-right-margin* 72)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
344 | (pprint-logical-block (stream nil :prefix "[" :suffix "]") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
345 | (when (plusp (length value)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
346 | (json-write (aref value 0))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
347 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
348 | for i from 1 below (length value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
349 | do (progn |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
350 | (write-char #\, stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
351 | (pprint-newline :fill) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
352 | (pprint-indent :block 0) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
353 | (json-write (aref value i) stream)))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
354 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
355 | (defmethod json-write ((value list) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
356 | "Encode a list to a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
357 | (let ((*print-pretty* t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
358 | (*print-length* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
359 | (*print-lines* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
360 | (*print-right-margin* 72)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
361 | (pprint-logical-block (stream value :prefix "[" :suffix "]") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
362 | (pprint-exit-if-list-exhausted) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
363 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
364 | (json-write (pprint-pop) stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
365 | (pprint-exit-if-list-exhausted) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
366 | (write-char #\, stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
367 | (pprint-newline :fill) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
368 | (pprint-indent :block 0))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
369 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
370 | (defmethod json-write ((value hash-table) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
371 | "Encode a hash-table to a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
372 | (let ((*print-pretty* t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
373 | (*print-length* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
374 | (*print-lines* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
375 | (*print-right-margin* 72)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
376 | (let ((keys (loop for key being each hash-keys in value collect key))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
377 | (pprint-logical-block (stream keys :prefix "{" :suffix "}") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
378 | (pprint-exit-if-list-exhausted) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
379 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
380 | (let ((key (pprint-pop))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
381 | (if (not (stringp key)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
382 | (progn |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
383 | (warn "~s is not a valid JSON key; skipping...~%" key) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
384 | (pprint-exit-if-list-exhausted)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
385 | (progn |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
386 | (json-write key stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
387 | (write-char #\: stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
388 | (json-write (gethash key value) stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
389 | (pprint-exit-if-list-exhausted) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
390 | (write-char #\, stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
391 | (pprint-newline :mandatory) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
392 | (pprint-indent :current 0))))))))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
393 | |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
394 | (defmethod json-write ((value json-object) &optional stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
395 | "Encode a JSON object with an associative list of members to a stream." |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
396 | (let ((*print-pretty* t) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
397 | (*print-length* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
398 | (*print-lines* nil) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
399 | (*print-right-margin* 72)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
400 | (pprint-logical-block (stream (json-object-members value) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
401 | :prefix "{" |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
402 | :suffix "}") |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
403 | (pprint-exit-if-list-exhausted) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
404 | (loop |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
405 | (let ((kv-pair (pprint-pop))) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
406 | (destructuring-bind (k v) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
407 | kv-pair |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
408 | (if (not (stringp k)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
409 | (progn |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
410 | (warn "~s is not a valid JSON key; skipping...~%" k) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
411 | (pprint-exit-if-list-exhausted)) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
412 | (progn |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
413 | (json-write k stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
414 | (write-char #\: stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
415 | (json-write v stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
416 | (pprint-exit-if-list-exhausted) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
417 | (write-char #\, stream) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
418 | (pprint-newline :mandatory) |
4ba88cac5bc7
num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff
changeset
|
419 | (pprint-indent :current 0))))))))) |