json.el 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. ;;; json.el --- JavaScript Object Notation parser / generator -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2006-2017 Free Software Foundation, Inc.
  3. ;; Author: Theresa O'Connor <ted@oconnor.cx>
  4. ;; Version: 1.4
  5. ;; Keywords: convenience
  6. ;; This file is part of GNU Emacs.
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;; This is a library for parsing and generating JSON (JavaScript Object
  19. ;; Notation).
  20. ;; Learn all about JSON here: <URL:http://json.org/>.
  21. ;; The user-serviceable entry points for the parser are the functions
  22. ;; `json-read' and `json-read-from-string'. The encoder has a single
  23. ;; entry point, `json-encode'.
  24. ;; Since there are several natural representations of key-value pair
  25. ;; mappings in elisp (alist, plist, hash-table), `json-read' allows you
  26. ;; to specify which you'd prefer (see `json-object-type' and
  27. ;; `json-array-type').
  28. ;; Similarly, since `false' and `null' are distinct in JSON, you can
  29. ;; distinguish them by binding `json-false' and `json-null' as desired.
  30. ;;; History:
  31. ;; 2006-03-11 - Initial version.
  32. ;; 2006-03-13 - Added JSON generation in addition to parsing. Various
  33. ;; other cleanups, bugfixes, and improvements.
  34. ;; 2006-12-29 - XEmacs support, from Aidan Kehoe <kehoea@parhasard.net>.
  35. ;; 2008-02-21 - Installed in GNU Emacs.
  36. ;; 2011-10-17 - Patch `json-alist-p' and `json-plist-p' to avoid recursion -tzz
  37. ;; 2012-10-25 - Added pretty-printed reformatting -Ryan Crum (ryan@ryancrum.org)
  38. ;;; Code:
  39. (require 'map)
  40. ;; Parameters
  41. (defvar json-object-type 'alist
  42. "Type to convert JSON objects to.
  43. Must be one of `alist', `plist', or `hash-table'. Consider let-binding
  44. this around your call to `json-read' instead of `setq'ing it. Ordering
  45. is maintained for `alist' and `plist', but not for `hash-table'.")
  46. (defvar json-array-type 'vector
  47. "Type to convert JSON arrays to.
  48. Must be one of `vector' or `list'. Consider let-binding this around
  49. your call to `json-read' instead of `setq'ing it.")
  50. (defvar json-key-type nil
  51. "Type to convert JSON keys to.
  52. Must be one of `string', `symbol', `keyword', or nil.
  53. If nil, `json-read' will guess the type based on the value of
  54. `json-object-type':
  55. If `json-object-type' is: nil will be interpreted as:
  56. `hash-table' `string'
  57. `alist' `symbol'
  58. `plist' `keyword'
  59. Note that values other than `string' might behave strangely for
  60. Sufficiently Weird keys. Consider let-binding this around your call to
  61. `json-read' instead of `setq'ing it.")
  62. (defvar json-false :json-false
  63. "Value to use when reading JSON `false'.
  64. If this has the same value as `json-null', you might not be able to tell
  65. the difference between `false' and `null'. Consider let-binding this
  66. around your call to `json-read' instead of `setq'ing it.")
  67. (defvar json-null nil
  68. "Value to use when reading JSON `null'.
  69. If this has the same value as `json-false', you might not be able to
  70. tell the difference between `false' and `null'. Consider let-binding
  71. this around your call to `json-read' instead of `setq'ing it.")
  72. (defvar json-encoding-separator ","
  73. "Value to use as an element separator when encoding.")
  74. (defvar json-encoding-default-indentation " "
  75. "The default indentation level for encoding.
  76. Used only when `json-encoding-pretty-print' is non-nil.")
  77. (defvar json--encoding-current-indentation "\n"
  78. "Internally used to keep track of the current indentation level of encoding.
  79. Used only when `json-encoding-pretty-print' is non-nil.")
  80. (defvar json-encoding-pretty-print nil
  81. "If non-nil, then the output of `json-encode' will be pretty-printed.")
  82. (defvar json-encoding-lisp-style-closings nil
  83. "If non-nil, ] and } closings will be formatted lisp-style,
  84. without indentation.")
  85. (defvar json-encoding-object-sort-predicate nil
  86. "Sorting predicate for JSON object keys during encoding.
  87. If nil, no sorting is performed. Else, JSON object keys are
  88. ordered by the specified sort predicate during encoding. For
  89. instance, setting this to `string<' will have JSON object keys
  90. ordered alphabetically.")
  91. (defvar json-pre-element-read-function nil
  92. "Function called (if non-nil) by `json-read-array' and
  93. `json-read-object' right before reading a JSON array or object,
  94. respectively. The function is called with one argument, which is
  95. the current JSON key.")
  96. (defvar json-post-element-read-function nil
  97. "Function called (if non-nil) by `json-read-array' and
  98. `json-read-object' right after reading a JSON array or object,
  99. respectively.")
  100. ;;; Utilities
  101. (defun json-join (strings separator)
  102. "Join STRINGS with SEPARATOR."
  103. (mapconcat 'identity strings separator))
  104. (defun json-alist-p (list)
  105. "Non-null if and only if LIST is an alist with simple keys."
  106. (while (consp list)
  107. (setq list (if (and (consp (car list))
  108. (atom (caar list)))
  109. (cdr list)
  110. 'not-alist)))
  111. (null list))
  112. (defun json-plist-p (list)
  113. "Non-null if and only if LIST is a plist with keyword keys."
  114. (while (consp list)
  115. (setq list (if (and (keywordp (car list))
  116. (consp (cdr list)))
  117. (cddr list)
  118. 'not-plist)))
  119. (null list))
  120. (defun json--plist-reverse (plist)
  121. "Return a copy of PLIST in reverse order.
  122. Unlike `reverse', this keeps the property-value pairs intact."
  123. (let (res)
  124. (while plist
  125. (let ((prop (pop plist))
  126. (val (pop plist)))
  127. (push val res)
  128. (push prop res)))
  129. res))
  130. (defun json--plist-to-alist (plist)
  131. "Return an alist of the property-value pairs in PLIST."
  132. (let (res)
  133. (while plist
  134. (let ((prop (pop plist))
  135. (val (pop plist)))
  136. (push (cons prop val) res)))
  137. (nreverse res)))
  138. (defmacro json--with-indentation (body)
  139. `(let ((json--encoding-current-indentation
  140. (if json-encoding-pretty-print
  141. (concat json--encoding-current-indentation
  142. json-encoding-default-indentation)
  143. "")))
  144. ,body))
  145. ;; Reader utilities
  146. (defsubst json-advance (&optional n)
  147. "Advance N characters forward."
  148. (forward-char n))
  149. (defsubst json-peek ()
  150. "Return the character at point."
  151. (following-char))
  152. (defsubst json-pop ()
  153. "Advance past the character at point, returning it."
  154. (let ((char (json-peek)))
  155. (if (zerop char)
  156. (signal 'json-end-of-file nil)
  157. (json-advance)
  158. char)))
  159. (defun json-skip-whitespace ()
  160. "Skip past the whitespace at point."
  161. ;; See
  162. ;; https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
  163. ;; or https://tools.ietf.org/html/rfc7159#section-2 for the
  164. ;; definition of whitespace in JSON.
  165. (skip-chars-forward "\t\r\n "))
  166. ;; Error conditions
  167. (define-error 'json-error "Unknown JSON error")
  168. (define-error 'json-readtable-error "JSON readtable error" 'json-error)
  169. (define-error 'json-unknown-keyword "Unrecognized keyword" 'json-error)
  170. (define-error 'json-number-format "Invalid number format" 'json-error)
  171. (define-error 'json-string-escape "Bad Unicode escape" 'json-error)
  172. (define-error 'json-string-format "Bad string format" 'json-error)
  173. (define-error 'json-key-format "Bad JSON object key" 'json-error)
  174. (define-error 'json-object-format "Bad JSON object" 'json-error)
  175. (define-error 'json-end-of-file "End of file while parsing JSON"
  176. '(end-of-file json-error))
  177. ;;; Paths
  178. (defvar json--path '()
  179. "Used internally by `json-path-to-position' to keep track of
  180. the path during recursive calls to `json-read'.")
  181. (defun json--record-path (key)
  182. "Record the KEY to the current JSON path.
  183. Used internally by `json-path-to-position'."
  184. (push (cons (point) key) json--path))
  185. (defun json--check-position (position)
  186. "Check if the last parsed JSON structure passed POSITION.
  187. Used internally by `json-path-to-position'."
  188. (let ((start (caar json--path)))
  189. (when (< start position (+ (point) 1))
  190. (throw :json-path (list :path (nreverse (mapcar #'cdr json--path))
  191. :match-start start
  192. :match-end (point)))))
  193. (pop json--path))
  194. (defun json-path-to-position (position &optional string)
  195. "Return the path to the JSON element at POSITION.
  196. When STRING is provided, return the path to the position in the
  197. string, else to the position in the current buffer.
  198. The return value is a property list with the following
  199. properties:
  200. :path -- A list of strings and numbers forming the path to
  201. the JSON element at the given position. Strings
  202. denote object names, while numbers denote array
  203. indexes.
  204. :match-start -- Position where the matched JSON element begins.
  205. :match-end -- Position where the matched JSON element ends.
  206. This can for instance be useful to determine the path to a JSON
  207. element in a deeply nested structure."
  208. (save-excursion
  209. (unless string
  210. (goto-char (point-min)))
  211. (let* ((json--path '())
  212. (json-pre-element-read-function #'json--record-path)
  213. (json-post-element-read-function
  214. (apply-partially #'json--check-position position))
  215. (path (catch :json-path
  216. (if string
  217. (json-read-from-string string)
  218. (json-read)))))
  219. (when (plist-get path :path)
  220. path))))
  221. ;;; Keywords
  222. (defvar json-keywords '("true" "false" "null")
  223. "List of JSON keywords.")
  224. ;; Keyword parsing
  225. (defun json-read-keyword (keyword)
  226. "Read a JSON keyword at point.
  227. KEYWORD is the keyword expected."
  228. (unless (member keyword json-keywords)
  229. (signal 'json-unknown-keyword (list keyword)))
  230. (mapc (lambda (char)
  231. (when (/= char (json-peek))
  232. (signal 'json-unknown-keyword
  233. (list (save-excursion
  234. (backward-word-strictly 1)
  235. (thing-at-point 'word)))))
  236. (json-advance))
  237. keyword)
  238. (unless (looking-at "\\(\\s-\\|[],}]\\|$\\)")
  239. (signal 'json-unknown-keyword
  240. (list (save-excursion
  241. (backward-word-strictly 1)
  242. (thing-at-point 'word)))))
  243. (cond ((string-equal keyword "true") t)
  244. ((string-equal keyword "false") json-false)
  245. ((string-equal keyword "null") json-null)))
  246. ;; Keyword encoding
  247. (defun json-encode-keyword (keyword)
  248. "Encode KEYWORD as a JSON value."
  249. (cond ((eq keyword t) "true")
  250. ((eq keyword json-false) "false")
  251. ((eq keyword json-null) "null")))
  252. ;;; Numbers
  253. ;; Number parsing
  254. (defun json-read-number (&optional sign)
  255. "Read the JSON number following point.
  256. The optional SIGN argument is for internal use.
  257. N.B.: Only numbers which can fit in Emacs Lisp's native number
  258. representation will be parsed correctly."
  259. ;; If SIGN is non-nil, the number is explicitly signed.
  260. (let ((number-regexp
  261. "\\([0-9]+\\)?\\(\\.[0-9]+\\)?\\([Ee][+-]?[0-9]+\\)?"))
  262. (cond ((and (null sign) (= (json-peek) ?-))
  263. (json-advance)
  264. (- (json-read-number t)))
  265. ((and (null sign) (= (json-peek) ?+))
  266. (json-advance)
  267. (json-read-number t))
  268. ((and (looking-at number-regexp)
  269. (or (match-beginning 1)
  270. (match-beginning 2)))
  271. (goto-char (match-end 0))
  272. (string-to-number (match-string 0)))
  273. (t (signal 'json-number-format (list (point)))))))
  274. ;; Number encoding
  275. (defun json-encode-number (number)
  276. "Return a JSON representation of NUMBER."
  277. (format "%s" number))
  278. ;;; Strings
  279. (defvar json-special-chars
  280. '((?\" . ?\")
  281. (?\\ . ?\\)
  282. (?b . ?\b)
  283. (?f . ?\f)
  284. (?n . ?\n)
  285. (?r . ?\r)
  286. (?t . ?\t))
  287. "Characters which are escaped in JSON, with their elisp counterparts.")
  288. ;; String parsing
  289. (defun json--decode-utf-16-surrogates (high low)
  290. "Return the code point represented by the UTF-16 surrogates HIGH and LOW."
  291. (+ (lsh (- high #xD800) 10) (- low #xDC00) #x10000))
  292. (defun json-read-escaped-char ()
  293. "Read the JSON string escaped character at point."
  294. ;; Skip over the '\'
  295. (json-advance)
  296. (let* ((char (json-pop))
  297. (special (assq char json-special-chars)))
  298. (cond
  299. (special (cdr special))
  300. ((not (eq char ?u)) char)
  301. ;; Special-case UTF-16 surrogate pairs,
  302. ;; cf. <https://tools.ietf.org/html/rfc7159#section-7>. Note that
  303. ;; this clause overlaps with the next one and therefore has to
  304. ;; come first.
  305. ((looking-at
  306. (rx (group (any "Dd") (any "89ABab") (= 2 (any xdigit)))
  307. "\\u" (group (any "Dd") (any "C-Fc-f") (= 2 (any xdigit)))))
  308. (json-advance 10)
  309. (json--decode-utf-16-surrogates
  310. (string-to-number (match-string 1) 16)
  311. (string-to-number (match-string 2) 16)))
  312. ((looking-at (rx (= 4 xdigit)))
  313. (let ((hex (match-string 0)))
  314. (json-advance 4)
  315. (string-to-number hex 16)))
  316. (t
  317. (signal 'json-string-escape (list (point)))))))
  318. (defun json-read-string ()
  319. "Read the JSON string at point."
  320. (unless (= (json-peek) ?\")
  321. (signal 'json-string-format (list "doesn't start with `\"'!")))
  322. ;; Skip over the '"'
  323. (json-advance)
  324. (let ((characters '())
  325. (char (json-peek)))
  326. (while (not (= char ?\"))
  327. (when (< char 32)
  328. (signal 'json-string-format (list (prin1-char char))))
  329. (push (if (= char ?\\)
  330. (json-read-escaped-char)
  331. (json-pop))
  332. characters)
  333. (setq char (json-peek)))
  334. ;; Skip over the '"'
  335. (json-advance)
  336. (if characters
  337. (concat (nreverse characters))
  338. "")))
  339. ;; String encoding
  340. (defun json-encode-string (string)
  341. "Return a JSON representation of STRING."
  342. ;; Reimplement the meat of `replace-regexp-in-string', for
  343. ;; performance (bug#20154).
  344. (let ((l (length string))
  345. (start 0)
  346. res mb)
  347. ;; Only escape quotation mark, backslash and the control
  348. ;; characters U+0000 to U+001F (RFC 4627, ECMA-404).
  349. (while (setq mb (string-match "[\"\\[:cntrl:]]" string start))
  350. (let* ((c (aref string mb))
  351. (special (rassq c json-special-chars)))
  352. (push (substring string start mb) res)
  353. (push (if special
  354. ;; Special JSON character (\n, \r, etc.).
  355. (string ?\\ (car special))
  356. ;; Fallback: UCS code point in \uNNNN form.
  357. (format "\\u%04x" c))
  358. res)
  359. (setq start (1+ mb))))
  360. (push (substring string start l) res)
  361. (push "\"" res)
  362. (apply #'concat "\"" (nreverse res))))
  363. (defun json-encode-key (object)
  364. "Return a JSON representation of OBJECT.
  365. If the resulting JSON object isn't a valid JSON object key,
  366. this signals `json-key-format'."
  367. (let ((encoded (json-encode object)))
  368. (unless (stringp (json-read-from-string encoded))
  369. (signal 'json-key-format (list object)))
  370. encoded))
  371. ;;; JSON Objects
  372. (defun json-new-object ()
  373. "Create a new Elisp object corresponding to a JSON object.
  374. Please see the documentation of `json-object-type'."
  375. (cond ((eq json-object-type 'hash-table)
  376. (make-hash-table :test 'equal))
  377. (t
  378. ())))
  379. (defun json-add-to-object (object key value)
  380. "Add a new KEY -> VALUE association to OBJECT.
  381. Returns the updated object, which you should save, e.g.:
  382. (setq obj (json-add-to-object obj \"foo\" \"bar\"))
  383. Please see the documentation of `json-object-type' and `json-key-type'."
  384. (let ((json-key-type
  385. (if (eq json-key-type nil)
  386. (cdr (assq json-object-type '((hash-table . string)
  387. (alist . symbol)
  388. (plist . keyword))))
  389. json-key-type)))
  390. (setq key
  391. (cond ((eq json-key-type 'string)
  392. key)
  393. ((eq json-key-type 'symbol)
  394. (intern key))
  395. ((eq json-key-type 'keyword)
  396. (intern (concat ":" key)))))
  397. (cond ((eq json-object-type 'hash-table)
  398. (puthash key value object)
  399. object)
  400. ((eq json-object-type 'alist)
  401. (cons (cons key value) object))
  402. ((eq json-object-type 'plist)
  403. (cons key (cons value object))))))
  404. ;; JSON object parsing
  405. (defun json-read-object ()
  406. "Read the JSON object at point."
  407. ;; Skip over the "{"
  408. (json-advance)
  409. (json-skip-whitespace)
  410. ;; read key/value pairs until "}"
  411. (let ((elements (json-new-object))
  412. key value)
  413. (while (not (= (json-peek) ?}))
  414. (json-skip-whitespace)
  415. (setq key (json-read-string))
  416. (json-skip-whitespace)
  417. (if (= (json-peek) ?:)
  418. (json-advance)
  419. (signal 'json-object-format (list ":" (json-peek))))
  420. (json-skip-whitespace)
  421. (when json-pre-element-read-function
  422. (funcall json-pre-element-read-function key))
  423. (setq value (json-read))
  424. (when json-post-element-read-function
  425. (funcall json-post-element-read-function))
  426. (setq elements (json-add-to-object elements key value))
  427. (json-skip-whitespace)
  428. (when (/= (json-peek) ?})
  429. (if (= (json-peek) ?,)
  430. (json-advance)
  431. (signal 'json-object-format (list "," (json-peek))))))
  432. ;; Skip over the "}"
  433. (json-advance)
  434. (pcase json-object-type
  435. (`alist (nreverse elements))
  436. (`plist (json--plist-reverse elements))
  437. (_ elements))))
  438. ;; Hash table encoding
  439. (defun json-encode-hash-table (hash-table)
  440. "Return a JSON representation of HASH-TABLE."
  441. (if json-encoding-object-sort-predicate
  442. (json-encode-alist (map-into hash-table 'list))
  443. (format "{%s%s}"
  444. (json-join
  445. (let (r)
  446. (json--with-indentation
  447. (maphash
  448. (lambda (k v)
  449. (push (format
  450. (if json-encoding-pretty-print
  451. "%s%s: %s"
  452. "%s%s:%s")
  453. json--encoding-current-indentation
  454. (json-encode-key k)
  455. (json-encode v))
  456. r))
  457. hash-table))
  458. r)
  459. json-encoding-separator)
  460. (if (or (not json-encoding-pretty-print)
  461. json-encoding-lisp-style-closings)
  462. ""
  463. json--encoding-current-indentation))))
  464. ;; List encoding (including alists and plists)
  465. (defun json-encode-alist (alist)
  466. "Return a JSON representation of ALIST."
  467. (when json-encoding-object-sort-predicate
  468. (setq alist
  469. (sort alist (lambda (a b)
  470. (funcall json-encoding-object-sort-predicate
  471. (car a) (car b))))))
  472. (format "{%s%s}"
  473. (json-join
  474. (json--with-indentation
  475. (mapcar (lambda (cons)
  476. (format (if json-encoding-pretty-print
  477. "%s%s: %s"
  478. "%s%s:%s")
  479. json--encoding-current-indentation
  480. (json-encode-key (car cons))
  481. (json-encode (cdr cons))))
  482. alist))
  483. json-encoding-separator)
  484. (if (or (not json-encoding-pretty-print)
  485. json-encoding-lisp-style-closings)
  486. ""
  487. json--encoding-current-indentation)))
  488. (defun json-encode-plist (plist)
  489. "Return a JSON representation of PLIST."
  490. (if json-encoding-object-sort-predicate
  491. (json-encode-alist (json--plist-to-alist plist))
  492. (let (result)
  493. (json--with-indentation
  494. (while plist
  495. (push (concat
  496. json--encoding-current-indentation
  497. (json-encode-key (car plist))
  498. (if json-encoding-pretty-print
  499. ": "
  500. ":")
  501. (json-encode (cadr plist)))
  502. result)
  503. (setq plist (cddr plist))))
  504. (concat "{"
  505. (json-join (nreverse result) json-encoding-separator)
  506. (if (and json-encoding-pretty-print
  507. (not json-encoding-lisp-style-closings))
  508. json--encoding-current-indentation
  509. "")
  510. "}"))))
  511. (defun json-encode-list (list)
  512. "Return a JSON representation of LIST.
  513. Tries to DWIM: simple lists become JSON arrays, while alists and plists
  514. become JSON objects."
  515. (cond ((null list) "null")
  516. ((json-alist-p list) (json-encode-alist list))
  517. ((json-plist-p list) (json-encode-plist list))
  518. ((listp list) (json-encode-array list))
  519. (t
  520. (signal 'json-error (list list)))))
  521. ;;; Arrays
  522. ;; Array parsing
  523. (defun json-read-array ()
  524. "Read the JSON array at point."
  525. ;; Skip over the "["
  526. (json-advance)
  527. (json-skip-whitespace)
  528. ;; read values until "]"
  529. (let (elements)
  530. (while (not (= (json-peek) ?\]))
  531. (json-skip-whitespace)
  532. (when json-pre-element-read-function
  533. (funcall json-pre-element-read-function (length elements)))
  534. (push (json-read) elements)
  535. (when json-post-element-read-function
  536. (funcall json-post-element-read-function))
  537. (json-skip-whitespace)
  538. (when (/= (json-peek) ?\])
  539. (if (= (json-peek) ?,)
  540. (json-advance)
  541. (signal 'json-error (list 'bleah)))))
  542. ;; Skip over the "]"
  543. (json-advance)
  544. (pcase json-array-type
  545. (`vector (nreverse (vconcat elements)))
  546. (`list (nreverse elements)))))
  547. ;; Array encoding
  548. (defun json-encode-array (array)
  549. "Return a JSON representation of ARRAY."
  550. (if (and json-encoding-pretty-print
  551. (> (length array) 0))
  552. (concat
  553. (json--with-indentation
  554. (concat (format "[%s" json--encoding-current-indentation)
  555. (json-join (mapcar 'json-encode array)
  556. (format "%s%s"
  557. json-encoding-separator
  558. json--encoding-current-indentation))))
  559. (format "%s]"
  560. (if json-encoding-lisp-style-closings
  561. ""
  562. json--encoding-current-indentation)))
  563. (concat "["
  564. (mapconcat 'json-encode array json-encoding-separator)
  565. "]")))
  566. ;;; JSON reader.
  567. (defvar json-readtable
  568. (let ((table
  569. '((?t json-read-keyword "true")
  570. (?f json-read-keyword "false")
  571. (?n json-read-keyword "null")
  572. (?{ json-read-object)
  573. (?\[ json-read-array)
  574. (?\" json-read-string))))
  575. (mapc (lambda (char)
  576. (push (list char 'json-read-number) table))
  577. '(?- ?+ ?. ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
  578. table)
  579. "Readtable for JSON reader.")
  580. (defun json-read ()
  581. "Parse and return the JSON object following point.
  582. Advances point just past JSON object."
  583. (json-skip-whitespace)
  584. (let ((char (json-peek)))
  585. (if (zerop char)
  586. (signal 'json-end-of-file nil)
  587. (let ((record (cdr (assq char json-readtable))))
  588. (if (functionp (car record))
  589. (apply (car record) (cdr record))
  590. (signal 'json-readtable-error record))))))
  591. ;; Syntactic sugar for the reader
  592. (defun json-read-from-string (string)
  593. "Read the JSON object contained in STRING and return it."
  594. (with-temp-buffer
  595. (insert string)
  596. (goto-char (point-min))
  597. (json-read)))
  598. (defun json-read-file (file)
  599. "Read the first JSON object contained in FILE and return it."
  600. (with-temp-buffer
  601. (insert-file-contents file)
  602. (goto-char (point-min))
  603. (json-read)))
  604. ;;; JSON encoder
  605. (defun json-encode (object)
  606. "Return a JSON representation of OBJECT as a string."
  607. (cond ((memq object (list t json-null json-false))
  608. (json-encode-keyword object))
  609. ((stringp object) (json-encode-string object))
  610. ((keywordp object) (json-encode-string
  611. (substring (symbol-name object) 1)))
  612. ((symbolp object) (json-encode-string
  613. (symbol-name object)))
  614. ((numberp object) (json-encode-number object))
  615. ((arrayp object) (json-encode-array object))
  616. ((hash-table-p object) (json-encode-hash-table object))
  617. ((listp object) (json-encode-list object))
  618. (t (signal 'json-error (list object)))))
  619. ;; Pretty printing
  620. (defun json-pretty-print-buffer ()
  621. "Pretty-print current buffer."
  622. (interactive)
  623. (json-pretty-print (point-min) (point-max)))
  624. (defun json-pretty-print (begin end)
  625. "Pretty-print selected region."
  626. (interactive "r")
  627. (atomic-change-group
  628. (let ((json-encoding-pretty-print t)
  629. ;; Ensure that ordering is maintained
  630. (json-object-type 'alist)
  631. (txt (delete-and-extract-region begin end)))
  632. (insert (json-encode (json-read-from-string txt))))))
  633. (defun json-pretty-print-buffer-ordered ()
  634. "Pretty-print current buffer with object keys ordered."
  635. (interactive)
  636. (let ((json-encoding-object-sort-predicate 'string<))
  637. (json-pretty-print-buffer)))
  638. (defun json-pretty-print-ordered (begin end)
  639. "Pretty-print the region with object keys ordered."
  640. (interactive "r")
  641. (let ((json-encoding-object-sort-predicate 'string<))
  642. (json-pretty-print begin end)))
  643. (provide 'json)
  644. ;;; json.el ends here