diff options
Diffstat (limited to 'lisp/json.el')
-rw-r--r-- | lisp/json.el | 101 |
1 files changed, 66 insertions, 35 deletions
diff --git a/lisp/json.el b/lisp/json.el index 1a455e3851b..d664dae05e4 100644 --- a/lisp/json.el +++ b/lisp/json.el @@ -53,6 +53,7 @@ ;;; Code: (require 'map) +(require 'subr-x) ;; Parameters @@ -370,7 +371,7 @@ representation will be parsed correctly." (defun json--decode-utf-16-surrogates (high low) "Return the code point represented by the UTF-16 surrogates HIGH and LOW." - (+ (lsh (- high #xD800) 10) (- low #xDC00) #x10000)) + (+ (ash (- high #xD800) 10) (- low #xDC00) #x10000)) (defun json-read-escaped-char () "Read the JSON string escaped character at point." @@ -523,8 +524,8 @@ Please see the documentation of `json-object-type' and `json-key-type'." ;; Skip over the "}" (json-advance) (pcase json-object-type - (`alist (nreverse elements)) - (`plist (json--plist-reverse elements)) + ('alist (nreverse elements)) + ('plist (json--plist-reverse elements)) (_ elements)))) ;; Hash table encoding @@ -609,8 +610,7 @@ Please see the documentation of `json-object-type' and `json-key-type'." "Return a JSON representation of LIST. Tries to DWIM: simple lists become JSON arrays, while alists and plists become JSON objects." - (cond ((null list) "null") - ((json-alist-p list) (json-encode-alist list)) + (cond ((json-alist-p list) (json-encode-alist list)) ((json-plist-p list) (json-encode-plist list)) ((listp list) (json-encode-array list)) (t @@ -642,8 +642,8 @@ become JSON objects." ;; Skip over the "]" (json-advance) (pcase json-array-type - (`vector (nreverse (vconcat elements))) - (`list (nreverse elements))))) + ('vector (nreverse (vconcat elements))) + ('list (nreverse elements))))) ;; Array encoding @@ -689,7 +689,19 @@ become JSON objects." (defun json-read () "Parse and return the JSON object following point. -Advances point just past JSON object." +Advances point just past JSON object. + +If called with the following JSON after point + + {\"a\": [1, 2, {\"c\": false}], + \"b\": \"foo\"} + +you will get the following structure returned: + + ((a . + [1 2 + ((c . :json-false))]) + (b . \"foo\"))" (json-skip-whitespace) (let ((char (json-peek))) (if (zerop char) @@ -717,48 +729,67 @@ Advances point just past JSON object." ;;; JSON encoder (defun json-encode (object) - "Return a JSON representation of OBJECT as a string." + "Return a JSON representation of OBJECT as a string. + +OBJECT should have a structure like one returned by `json-read'. +If an error is detected during encoding, an error based on +`json-error' is signalled." (cond ((memq object (list t json-null json-false)) (json-encode-keyword object)) ((stringp object) (json-encode-string object)) ((keywordp object) (json-encode-string (substring (symbol-name object) 1))) + ((listp object) (json-encode-list object)) ((symbolp object) (json-encode-string (symbol-name object))) ((numberp object) (json-encode-number object)) ((arrayp object) (json-encode-array object)) ((hash-table-p object) (json-encode-hash-table object)) - ((listp object) (json-encode-list object)) (t (signal 'json-error (list object))))) -;; Pretty printing - -(defun json-pretty-print-buffer () - "Pretty-print current buffer." - (interactive) - (json-pretty-print (point-min) (point-max))) - -(defun json-pretty-print (begin end) - "Pretty-print selected region." - (interactive "r") - (atomic-change-group - (let ((json-encoding-pretty-print t) - ;; Ensure that ordering is maintained - (json-object-type 'alist) - (txt (delete-and-extract-region begin end))) - (insert (json-encode (json-read-from-string txt)))))) - -(defun json-pretty-print-buffer-ordered () - "Pretty-print current buffer with object keys ordered." - (interactive) +;; Pretty printing & minimizing + +(defun json-pretty-print-buffer (&optional minimize) + "Pretty-print current buffer. +With prefix argument MINIMIZE, minimize it instead." + (interactive "P") + (json-pretty-print (point-min) (point-max) minimize)) + +(defun json-pretty-print (begin end &optional minimize) + "Pretty-print selected region. +With prefix argument MINIMIZE, minimize it instead." + (interactive "r\nP") + (let ((json-encoding-pretty-print (null minimize)) + ;; Distinguish an empty objects from 'null' + (json-null :json-null) + ;; Ensure that ordering is maintained + (json-object-type 'alist) + (err (gensym)) + json) + (save-restriction + (narrow-to-region begin end) + (goto-char begin) + (while (not (eq (setq json (condition-case _ + (json-read) + (json-error err))) + err)) + (delete-region begin (point)) + (insert (json-encode json)) + (setq begin (point)))))) + +(defun json-pretty-print-buffer-ordered (&optional minimize) + "Pretty-print current buffer with object keys ordered. +With prefix argument MINIMIZE, minimize it instead." + (interactive "P") (let ((json-encoding-object-sort-predicate 'string<)) - (json-pretty-print-buffer))) + (json-pretty-print-buffer minimize))) -(defun json-pretty-print-ordered (begin end) - "Pretty-print the region with object keys ordered." - (interactive "r") +(defun json-pretty-print-ordered (begin end &optional minimize) + "Pretty-print the region with object keys ordered. +With prefix argument MINIMIZE, minimize it instead." + (interactive "r\nP") (let ((json-encoding-object-sort-predicate 'string<)) - (json-pretty-print begin end))) + (json-pretty-print begin end minimize))) (provide 'json) |