Browse Source

Minimal JSON reader for CL

master
Yuki Izumi 8 years ago
commit
6f49570ef4
No account linked to committer's email address
2 changed files with 75 additions and 0 deletions
  1. 18
    0
      README.md
  2. 57
    0
      minimal-json.lisp

+ 18
- 0
README.md View File

@@ -0,0 +1,18 @@
```lisp
CL-USER> {"literal": "json syntax", "pretty": {"cool": "I think."}}
{"literal": "json syntax", "pretty": {"cool": "I think."}}
CL-USER> (setf *eg* {"literal": "json syntax", "pretty": {"cool": "I think."}})
{"literal": "json syntax", "pretty": {"cool": "I think."}}
CL-USER> (gethash "literal" *eg*)
"json syntax"
T
CL-USER> (gethash "pretty" *eg*)
{"cool": "I think."}
T
CL-USER> (gethash "cool" (gethash "pretty" *eg*))
"I think."
T
CL-USER> { "abc": 1, "def": {"x": "y", "m": (1 2 3 raw lisp oh my) } }
{"abc": 1, "def": {"x": "y", "m": (1 2 3 RAW LISP OH MY)}}
CL-USER>
```

+ 57
- 0
minimal-json.lisp View File

@@ -0,0 +1,57 @@
(defun json-skip-whitespace (stream)
(do () ((let ((next (peek-char nil stream)))
(and (char/= next #\Space)
(char/= next #\Tab)
(char/= next #\Newline)
(char/= next #\Return))))
(read-char stream)))

(defun json-expect-char (stream char)
(let ((actual (read-char stream)))
(when (char/= char actual)
(error (format nil "Expected ~s, got ~s" char actual)))))

(defun json-read-value (stream)
(read stream))

(defun json-read-object-inner (stream object)
(let ((key (read stream t nil t)))
(json-skip-whitespace stream)
(json-expect-char stream #\:)
(let ((value (json-read-value stream)))
(setf (gethash key object) value)))
(json-skip-whitespace stream)
(ecase (peek-char nil stream)
(#\}
object)
(#\,
(read-char stream)
(json-read-object-inner stream object))))

(defun json-read-object (stream)
(json-expect-char stream #\{)
(let ((object (make-hash-table :test 'equal)))
(json-read-object-inner stream object)
(json-expect-char stream #\})
object))

(defun json-reader (stream char)
(unread-char char stream)
(json-read-object stream))

(defmethod print-object ((hash-table hash-table) stream)
(format stream "{")
(with-hash-table-iterator (iterator hash-table)
(loop with first = t
do (multiple-value-bind (entry-p key value) (iterator)
(when (not entry-p)
(return))
(if first
(setf first nil)
(format stream ", "))
(prin1 key stream)
(format stream ": ")
(prin1 value stream))))
(format stream "}"))

(set-macro-character #\{ #'json-reader)

Loading…
Cancel
Save