a JSON reader for Common Lisp
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

minimal-json.lisp 1.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. (defun json-skip-whitespace (stream)
  2. (do () ((let ((next (peek-char nil stream)))
  3. (and (char/= next #\Space)
  4. (char/= next #\Tab)
  5. (char/= next #\Newline)
  6. (char/= next #\Return))))
  7. (read-char stream)))
  8. (defun json-expect-char (stream char)
  9. (let ((actual (read-char stream)))
  10. (when (char/= char actual)
  11. (error (format nil "Expected ~s, got ~s" char actual)))))
  12. (defun json-read-value (stream)
  13. (read stream))
  14. (defun json-read-object-inner (stream object)
  15. (let ((key (read stream t nil t)))
  16. (json-skip-whitespace stream)
  17. (json-expect-char stream #\:)
  18. (let ((value (json-read-value stream)))
  19. (setf (gethash key object) value)))
  20. (json-skip-whitespace stream)
  21. (ecase (peek-char nil stream)
  22. (#\}
  23. object)
  24. (#\,
  25. (read-char stream)
  26. (json-read-object-inner stream object))))
  27. (defun json-read-object (stream)
  28. (json-expect-char stream #\{)
  29. (let ((object (make-hash-table :test 'equal)))
  30. (json-read-object-inner stream object)
  31. (json-expect-char stream #\})
  32. object))
  33. (defun json-reader (stream char)
  34. (unread-char char stream)
  35. (json-read-object stream))
  36. (defmethod print-object ((hash-table hash-table) stream)
  37. (format stream "{")
  38. (with-hash-table-iterator (iterator hash-table)
  39. (loop with first = t
  40. do (multiple-value-bind (entry-p key value) (iterator)
  41. (when (not entry-p)
  42. (return))
  43. (if first
  44. (setf first nil)
  45. (format stream ", "))
  46. (prin1 key stream)
  47. (format stream ": ")
  48. (prin1 value stream))))
  49. (format stream "}"))
  50. (set-macro-character #\{ #'json-reader)