unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Damien Cassou <damien@cassou.me>
To: Yoichi Nakayama <yoichi.nakayama@gmail.com>
Cc: Philipp Stephani <phst@google.com>,
	Mark Oteiza <mvoteiza@udel.edu>,
	Theresa O'Connor <ted@oconnor.cx>,
	24252@debbugs.gnu.org, Dmitry Gutov <dgutov@yandex.ru>
Subject: bug#24252: 25.1; json.el doesn't distinguish null and empty object
Date: Sat, 19 May 2018 08:52:42 +0200	[thread overview]
Message-ID: <87o9hci1c5.fsf@cassou.me> (raw)
In-Reply-To: <m2eg5nwinp.fsf@gizaemon.local.i-did-not-set--mail-host-address--so-tickle-me> (Yoichi Nakayama's message of "Wed, 17 Aug 2016 23:54:02 +0900")

[-- Attachment #1: Type: text/plain, Size: 499 bytes --]

Yoichi Nakayama <yoichi.nakayama@gmail.com> writes:
> When json-pretty-print applied to "{}", it is
> unexpectedly converted to "null".
> This is caused by internal representations of null
> and empty object are the same:
>   (json-read-from-string "{}") ; => nil
>   (json-read-from-string "null") ; => nil

please find a patch attached. This patch uses :json-null to distinguish,
during pretty-print, between the value null and an empty object.

All tests pass and many new tests are added.

Best

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fix-pretty-printing-empty-objects-as-null.patch --]
[-- Type: text/x-patch, Size: 4751 bytes --]

From 78eb7b659809444f7c9690db73e1f65843d5658c Mon Sep 17 00:00:00 2001
From: Damien Cassou <damien@cassou.me>
Date: Sat, 19 May 2018 08:36:32 +0200
Subject: [PATCH] Fix pretty-printing empty objects as null

* lisp/json.el (json-pretty-print): Force distinction between empty
  objects and null.
(json-encode-list): Remove responsibility to print "null" as this
value is not a list.
(json-encode): Give higher precedence to lists so that an empty list
is printed as an empty object, not as "null".

* test/lisp/json-tests.el (test-json-encode): Add many tests to check
  the behavior of pretty-printing.
---
 lisp/json.el            |  7 +++--
 test/lisp/json-tests.el | 67 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/lisp/json.el b/lisp/json.el
index d374f452e6..cd95ec2832 100644
--- a/lisp/json.el
+++ b/lisp/json.el
@@ -609,8 +609,7 @@ json-encode-list
   "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
@@ -723,12 +722,12 @@ json-encode
         ((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
@@ -743,6 +742,8 @@ json-pretty-print
   (interactive "r")
   (atomic-change-group
     (let ((json-encoding-pretty-print t)
+          ;; Distinguish an empty objects from 'null'
+          (json-null :json-null)
           ;; Ensure that ordering is maintained
           (json-object-type 'alist)
           (txt (delete-and-extract-region begin end)))
diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el
index ea562e8b13..84039c09ce 100644
--- a/test/lisp/json-tests.el
+++ b/test/lisp/json-tests.el
@@ -325,5 +325,72 @@ json-tests--with-temp-buffer
   (with-temp-buffer
     (should-error (json-encode (current-buffer)) :type 'json-error)))
 
+;;; Pretty-print
+
+(defun json-tests-equal-pretty-print (original &optional expected)
+  "Abort current test if pretty-printing ORIGINAL does not yield EXPECTED.
+
+Both ORIGINAL and EXPECTED should be strings.  If EXPECTED is
+nil, ORIGINAL should stay unchanged by pretty-printing."
+  (with-temp-buffer
+    (insert original)
+    (json-pretty-print-buffer)
+    (should (equal (buffer-string) (or expected original)))))
+
+(ert-deftest test-json-pretty-print-string ()
+  (json-tests-equal-pretty-print "\"\"")
+  (json-tests-equal-pretty-print "\"foo\""))
+
+(ert-deftest test-json-pretty-print-atom ()
+  (json-tests-equal-pretty-print "true")
+  (json-tests-equal-pretty-print "false")
+  (json-tests-equal-pretty-print "null"))
+
+(ert-deftest test-json-pretty-print-number ()
+  (json-tests-equal-pretty-print "123")
+  (json-tests-equal-pretty-print "0.123"))
+
+(ert-deftest test-json-pretty-print-object ()
+  ;; empty (regression test for bug#24252)
+  (json-tests-equal-pretty-print
+   "{}"
+   "{\n}")
+  ;; one pair
+  (json-tests-equal-pretty-print
+   "{\"key\":1}"
+   "{\n  \"key\": 1\n}")
+  ;; two pairs
+  (json-tests-equal-pretty-print
+   "{\"key1\":1,\"key2\":2}"
+   "{\n  \"key1\": 1,\n  \"key2\": 2\n}")
+  ;; embedded object
+  (json-tests-equal-pretty-print
+   "{\"foo\":{\"key\":1}}"
+   "{\n  \"foo\": {\n    \"key\": 1\n  }\n}")
+  ;; embedded array
+  (json-tests-equal-pretty-print
+   "{\"key\":[1,2]}"
+   "{\n  \"key\": [\n    1,\n    2\n  ]\n}"))
+
+(ert-deftest test-json-pretty-print-array ()
+  ;; empty
+  (json-tests-equal-pretty-print "[]")
+  ;; one item
+  (json-tests-equal-pretty-print
+   "[1]"
+   "[\n  1\n]")
+  ;; two items
+  (json-tests-equal-pretty-print
+   "[1,2]"
+   "[\n  1,\n  2\n]")
+  ;; embedded object
+  (json-tests-equal-pretty-print
+   "[{\"key\":1}]"
+   "[\n  {\n    \"key\": 1\n  }\n]")
+  ;; embedded array
+  (json-tests-equal-pretty-print
+   "[[1,2]]"
+   "[\n  [\n    1,\n    2\n  ]\n]"))
+
 (provide 'json-tests)
 ;;; json-tests.el ends here
-- 
2.17.0


[-- Attachment #3: Type: text/plain, Size: 164 bytes --]


-- 
Damien Cassou
http://damiencassou.seasidehosting.st

"Success is the ability to go from one failure to another without
losing enthusiasm." --Winston Churchill

  parent reply	other threads:[~2018-05-19  6:52 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-17 14:54 bug#24252: 25.1; json.el doesn't distinguish null and empty object Yoichi Nakayama
2016-08-19  2:06 ` Dmitry Gutov
2016-08-19 23:45   ` Yoichi Nakayama
2016-08-20  0:52     ` Dmitry Gutov
2016-08-20  6:12       ` Yoichi Nakayama
2016-08-21  1:30         ` Yoichi Nakayama
2016-08-21  3:42         ` Dmitry Gutov
2016-08-21 12:11           ` Yoichi Nakayama
2016-08-21 13:32             ` Yoichi Nakayama
2016-08-21 15:06               ` Yoichi Nakayama
2016-08-27  0:05                 ` Dmitry Gutov
2018-05-17 14:39                 ` Damien Cassou
2018-05-19  6:52 ` Damien Cassou [this message]
2018-05-28 15:21   ` Nicolas Petton
2018-06-11 13:36     ` Damien Cassou
2018-06-12 17:14       ` Eli Zaretskii
2018-06-13  7:13         ` Damien Cassou
2018-06-13 13:05           ` Nicolas Petton
2018-06-13 16:55             ` Eli Zaretskii
2018-06-14  9:04               ` Nicolas Petton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87o9hci1c5.fsf@cassou.me \
    --to=damien@cassou.me \
    --cc=24252@debbugs.gnu.org \
    --cc=dgutov@yandex.ru \
    --cc=mvoteiza@udel.edu \
    --cc=phst@google.com \
    --cc=ted@oconnor.cx \
    --cc=yoichi.nakayama@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).