changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate lisp/lib/dat/json.lisp

changeset 395: d876b572b5b9
parent: 58d7c3925687
child: ea4f008ad13f
author: Richard Westhaver <ellis@rwest.io>
date: Sun, 02 Jun 2024 02:30:54 -0400
permissions: -rw-r--r--
description: updates
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
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
15
 (defclass json-object ()
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
16
   ((members :initform nil
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
17
             :initarg :members
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
18
             :accessor json-object-members))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
19
   (: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
20
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
21
 (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
22
   "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
23
   (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
24
     (let ((*print-level* 1))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
25
       (json-encode obj stream))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
26
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
27
 (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
28
   "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
29
   (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
30
     (if (null place)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
31
         value
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
32
       (values (second place) t))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
33
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
34
 (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
35
   "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
36
   (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
37
     (prog1 value
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
38
       (if (null place)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
39
           (let ((k (if (stringp key)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
40
                        key
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
41
                      (princ-to-string key))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
42
             (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
43
         (rplacd place (list value))))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
44
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
45
 (defsetf json-getf json-setf)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
46
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
47
 (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
48
   "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
49
   (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
50
     (values (json-read stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
51
             (file-position stream))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
52
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
53
 (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
54
   (declare (ignore format))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
55
   (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
56
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
57
 (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
58
   "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
59
   (json-write value stream))
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
 (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
62
   (declare (ignore format))
225
Richard Westhaver <ellis@rwest.io>
parents: 122
diff changeset
63
   (if stream
Richard Westhaver <ellis@rwest.io>
parents: 122
diff changeset
64
       (json-encode obj stream)
Richard Westhaver <ellis@rwest.io>
parents: 122
diff changeset
65
       (with-output-to-string (s)
Richard Westhaver <ellis@rwest.io>
parents: 122
diff changeset
66
         (json-encode obj s)
Richard Westhaver <ellis@rwest.io>
parents: 122
diff changeset
67
         s)))
122
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
68
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
69
 (defun json-enable-reader-macro ()
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
70
   "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
71
   (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
72
            (declare (ignorable char n))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
73
            (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
74
              (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
75
                 for key = (pop xs)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
76
                 for value = (pop xs)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
77
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
78
                 ;; stop when nothing is left
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
79
                 unless (or xs key value)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
80
                 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
81
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
82
                 ;; 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
83
                 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
84
                 into pairs))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
85
     (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
86
     (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
87
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
88
 (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
89
   "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
90
   (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
91
     (case c
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
92
       (:eof eof-value)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
93
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
94
       ;; constants, objects, lists, and strings
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
95
       (#\t (json-read-true stream))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
96
       (#\f (json-read-false stream))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
97
       (#\n (json-read-null stream))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
98
       (#\{ (json-read-object stream))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
99
       (#\[ (json-read-list stream))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
100
       (#\" (json-read-string stream))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
101
       ;; must be a number
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
102
       (otherwise (json-read-number stream)))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
103
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
104
 (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
105
   "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
106
   (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
107
   (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
108
     (read-char stream)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
109
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
110
 (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
111
   "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
112
   (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
113
   (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
114
       t
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
115
     (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
116
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
117
 (defun json-read-true (stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
118
   "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
119
   (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
120
   (json-read-char stream #\r)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
121
   (json-read-char stream #\u)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
122
   (json-read-char stream #\e))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
123
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
124
 (defun json-read-false (stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
125
   "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
126
   (prog1 nil
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
127
     (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
128
     (json-read-char stream #\a)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
129
     (json-read-char stream #\l)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
130
     (json-read-char stream #\s)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
131
     (json-read-char stream #\e)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
132
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
133
 (defun json-read-null (stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
134
   "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
135
   (prog1 nil
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
136
     (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
137
     (json-read-char stream #\u)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
138
     (json-read-char stream #\l)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
139
     (json-read-char stream #\l)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
140
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
141
 (defun json-read-number (stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
142
   "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
143
   (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
144
   (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
145
              (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
146
                (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
147
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
148
              ;; 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
149
              (labels ((read-digits ()
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
150
                         (let ((c (read-char stream)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
151
                           (unless (digit-char-p c)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
152
                             (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
153
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
154
                           ;; write the digits
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
155
                           (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
156
                              (write-char c s)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
157
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
158
                              ;; next digit, test for eof
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
159
                              (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
160
                                (return))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
161
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
162
                              ;; ensure digit
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
                                (return (unread-char c stream))))))
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
                       ;; fractional component
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
167
                       (read-fraction ()
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
168
                         (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
169
                           (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
170
                           (read-digits)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
171
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
172
                       ;; exponent
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
173
                       (read-exponent ()
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
174
                         (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
175
                           (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
176
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
177
                           ;; optional sign
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
178
                           (case (peek-char nil stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
179
                             (#\- (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
180
                             (#\+ (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
181
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
182
                           ;; exponent
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
183
                           (read-digits))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
184
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
185
                ;; 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
186
                (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
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
                  (read-digits))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
189
                (read-fraction)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
190
                (read-exponent)))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
191
     (prog1
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
192
       (read-from-string 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
 (defun json-read-string (stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
195
   "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
196
   (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
197
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
198
   ;; read the expected quote
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
199
   (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
200
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
201
   ;; read into an output buffer
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
202
   (with-output-to-string (s)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
203
     (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
204
        for c = (read-char stream)
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
        ;; stop at closing quote
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
207
        until (char= c #\")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
208
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
209
        ;; write character to output
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
210
        do (if (char/= c #\\)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
211
               (write-char c s)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
212
             (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
213
                        (#\n #\newline)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
214
                        (#\t #\tab)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
215
                        (#\f #\formfeed)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
216
                        (#\b #\backspace)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
217
                        (#\r #\return)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
218
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
219
                        ;; read unicode character
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
220
                        (#\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
221
                                   (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
222
                                   (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
223
                                   (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
224
                               (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
225
                                                  (ash x2  8)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
226
                                                  (ash x3  4)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
227
                                                  (ash x4  0)))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
228
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
229
                        ;; verbatim character
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
230
                        (otherwise c))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
231
               (write-char c s))))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
232
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
233
 (defun json-read-list (stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
234
   "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
235
   (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
236
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
237
   ;; read the expected open bracket
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
238
   (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
239
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
240
   ;; check for an empty list
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
241
   (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
242
       nil
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
243
     (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
244
        for x = (json-read stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
245
        collect x
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
246
        into xs
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
247
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
248
        ;; check for another element
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
249
        while (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
250
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
251
        ;; return the final list
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
252
        finally (return (prog1 xs
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
253
                          (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
254
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
255
 (defun json-read-object (stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
256
   "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
257
   (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
258
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
259
   ;; read the expected open brace
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
260
   (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
261
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
262
   ;; check for an empty object
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
263
   (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
264
       (make-instance 'json-object)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
265
     (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
266
        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
267
        for value = (progn
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
268
                      (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
269
                      (json-read stream))
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
        ;; 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
272
        collect (list key value)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
273
        into xs
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
274
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
275
        ;; check for another element
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
276
        while (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
277
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
278
        ;; return the final list
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
279
        finally (return (prog1 (make-instance 'json-object :members xs)
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
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
282
 (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
283
   "Encode the true value."
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
284
   (declare (ignore value))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
285
   (format stream "~<true~>"))
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
 (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
288
   "Encode the null constant."
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
289
   (declare (ignore value))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
290
   (format stream "~<null~>"))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
291
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
292
 (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
293
   "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
294
   (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
295
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
296
 (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
297
   "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
298
   (format stream "~<~a~>" value))
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 ratio) &optional stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
301
   "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
302
   (format stream "~<~a~>" (float value)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
303
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
304
 (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
305
   "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
306
   (flet ((encode-char (c)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
307
            (cond
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
308
             ((char= c #\\) "\\\\")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
309
             ((char= c #\") "\\\"")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
310
             ((char= c #\newline) "\\n")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
311
             ((char= c #\tab) "\\t")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
312
             ((char= c #\formfeed) "\\f")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
313
             ((char= c #\backspace) "\\b")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
314
             ((char= c #\return) "\\r")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
315
             ((char> c #\~)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
316
              (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
317
             (t
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
318
              (string c)))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
319
     (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
320
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
321
 (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
322
   "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
323
   (json-write (namestring value) stream))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
324
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
325
 (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
326
   "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
327
   (let ((*print-pretty* t)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
328
         (*print-length* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
329
         (*print-lines* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
330
         (*print-right-margin* 72))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
331
     (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
332
       (when (plusp (length value))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
333
         (json-write (aref value 0)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
334
       (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
335
          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
336
          do (progn
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
337
               (write-char #\, stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
338
               (pprint-newline :fill)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
339
               (pprint-indent :block 0)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
340
               (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
341
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
342
 (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
343
   "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
344
   (let ((*print-pretty* t)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
345
         (*print-length* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
346
         (*print-lines* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
347
         (*print-right-margin* 72))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
348
     (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
349
       (pprint-exit-if-list-exhausted)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
350
       (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
351
          (json-write (pprint-pop) stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
352
          (pprint-exit-if-list-exhausted)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
353
          (write-char #\, stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
354
          (pprint-newline :fill)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
355
          (pprint-indent :block 0)))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
356
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
357
 (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
358
   "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
359
   (let ((*print-pretty* t)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
360
         (*print-length* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
361
         (*print-lines* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
362
         (*print-right-margin* 72))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
363
     (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
364
       (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
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
         (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
367
            (let ((key (pprint-pop)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
368
              (if (not (stringp key))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
369
                  (progn
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
370
                    (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
371
                    (pprint-exit-if-list-exhausted))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
372
                (progn
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
373
                  (json-write key stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
374
                  (write-char #\: stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
375
                  (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
376
                  (pprint-exit-if-list-exhausted)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
377
                  (write-char #\, stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
378
                  (pprint-newline :mandatory)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
379
                  (pprint-indent :current 0)))))))))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
380
 
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
381
 (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
382
   "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
383
   (let ((*print-pretty* t)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
384
         (*print-length* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
385
         (*print-lines* nil)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
386
         (*print-right-margin* 72))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
387
     (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
388
                                   :prefix "{"
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
389
                                   :suffix "}")
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
390
       (pprint-exit-if-list-exhausted)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
391
       (loop
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
392
          (let ((kv-pair (pprint-pop)))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
393
            (destructuring-bind (k v)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
394
                kv-pair
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
395
              (if (not (stringp k))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
396
                  (progn
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
397
                    (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
398
                    (pprint-exit-if-list-exhausted))
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
399
                (progn
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
400
                  (json-write k stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
401
                  (write-char #\: stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
402
                  (json-write v stream)
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
                  (write-char #\, stream)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
405
                  (pprint-newline :mandatory)
4ba88cac5bc7 num/parse, added DAT system, net/fetch, time/local, refactored trees
ellis <ellis@rwest.io>
parents:
diff changeset
406
                  (pprint-indent :current 0)))))))))