emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

emacs-30 e55e2e1c6ba: Make json-serialize always return a unibyte string


From: Mattias Engdegård
Subject: emacs-30 e55e2e1c6ba: Make json-serialize always return a unibyte string (bug#70007)
Date: Sun, 8 Sep 2024 14:32:53 -0400 (EDT)

branch: emacs-30
commit e55e2e1c6baebbd105f930fa553ec65c74a3000d
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>

    Make json-serialize always return a unibyte string (bug#70007)
    
    The JSON format is defined as a byte sequence and will always be used as
    such, so returning a multibyte string makes little sense.
    
    * src/json.c (json_out_to_string): Remove.
    (Fjson_serialize): Return unibyte string.
    * test/src/json-tests.el (json-serialize/roundtrip)
    (json-serialize/roundtrip-scalars, json-serialize/string):
    Update tests.
    * doc/lispref/text.texi (Parsing JSON): Document.
    * etc/NEWS: Announce.
---
 doc/lispref/text.texi  |  2 +-
 etc/NEWS               |  7 +++++++
 src/json.c             | 14 ++------------
 test/src/json-tests.el | 50 ++++++++++++++++++++++++++------------------------
 4 files changed, 36 insertions(+), 37 deletions(-)

diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 278b53d7f65..df56433fd18 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -5844,7 +5844,7 @@ can be serialized to JSON@.  Likewise, the parsing 
functions will
 return any of the possible types described above.
 
 @defun json-serialize object &rest args
-This function returns a new Lisp string which contains the JSON
+This function returns a new Lisp unibyte string which contains the JSON
 representation of @var{object}.  The argument @var{args} is a list of
 keyword/argument pairs.  The following keywords are accepted:
 
diff --git a/etc/NEWS b/etc/NEWS
index a61bdc4a7f3..239182427bb 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -3071,6 +3071,13 @@ entire SQL file.
 
 ** JSON
 
++++
+*** 'json-serialize' now always returns a unibyte string.
+This is appropriate since it is an encoding operation.  In the unlikely
+event that a multibyte string is needed, the result can be decoded using
+
+  (decode-coding-string RESULT 'utf-8)
+
 ---
 *** The parser keeps duplicated object keys in alist and plist output.
 A JSON object such as '{"a":1,"a":2}' will now be translated into the
diff --git a/src/json.c b/src/json.c
index 21066d21328..41566f8369b 100644
--- a/src/json.c
+++ b/src/json.c
@@ -559,16 +559,6 @@ json_out_something (json_out_t *jo, Lisp_Object obj)
     wrong_type_argument (Qjson_value_p, obj);
 }
 
-static Lisp_Object
-json_out_to_string (json_out_t *jo)
-{
-  /* FIXME: should this be a unibyte or multibyte string?
-     Right now we make a multibyte string for test compatibility,
-     but we are really encoding so unibyte would make more sense.  */
-  ptrdiff_t nchars = jo->size - jo->chars_delta;
-  return make_multibyte_string (jo->buf, nchars, jo->size);
-}
-
 static void
 json_serialize (json_out_t *jo, Lisp_Object object,
                ptrdiff_t nargs, Lisp_Object *args)
@@ -596,7 +586,7 @@ json_serialize (json_out_t *jo, Lisp_Object object,
 
 DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, MANY,
        NULL,
-       doc: /* Return the JSON representation of OBJECT as a string.
+       doc: /* Return the JSON representation of OBJECT as a unibyte string.
 
 OBJECT is translated as follows:
 
@@ -629,7 +619,7 @@ usage: (json-serialize OBJECT &rest ARGS)  */)
   specpdl_ref count = SPECPDL_INDEX ();
   json_out_t jo;
   json_serialize (&jo, args[0], nargs - 1, args + 1);
-  return unbind_to (count, json_out_to_string (&jo));
+  return unbind_to (count, make_unibyte_string (jo.buf, jo.size));
 }
 
 DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, MANY,
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
index ebac70fb1c7..1d7491a4593 100644
--- a/test/src/json-tests.el
+++ b/test/src/json-tests.el
@@ -36,7 +36,7 @@
          (json
           "[null,false,true,0,123,-456,3.75,\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"]")
          (json-bytes (encode-coding-string json 'utf-8)))
-    (should (equal (json-serialize lisp) json))  ; or `json-bytes'?
+    (should (equal (json-serialize lisp) json-bytes))
     (with-temp-buffer
       ;; multibyte buffer
       (json-insert lisp)
@@ -82,28 +82,29 @@
                    "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
     (cl-destructuring-bind (lisp json) case
       (ert-info ((format "%S ↔ %S" lisp json))
-        (should (equal (json-serialize lisp) json))
-        (with-temp-buffer
-          (json-insert lisp)
-          (should (equal (buffer-string) json))
-          (should (eobp)))
-        (with-temp-buffer
-          (set-buffer-multibyte nil)
-          (json-insert lisp)
-          (should (equal (buffer-string) (encode-coding-string json 'utf-8)))
-          (should (eobp)))
-        (should (equal (json-parse-string json) lisp))
-        (with-temp-buffer
-          (insert json)
-          (goto-char 1)
-          (should (equal (json-parse-buffer) lisp))
-          (should (eobp)))
-        (with-temp-buffer
-          (set-buffer-multibyte nil)
-          (insert (encode-coding-string json 'utf-8))
-          (goto-char 1)
-          (should (equal (json-parse-buffer) lisp))
-          (should (eobp)))))))
+        (let ((json-bytes (encode-coding-string json 'utf-8)))
+          (should (equal (json-serialize lisp) json-bytes))
+          (with-temp-buffer
+            (json-insert lisp)
+            (should (equal (buffer-string) json))
+            (should (eobp)))
+          (with-temp-buffer
+            (set-buffer-multibyte nil)
+            (json-insert lisp)
+            (should (equal (buffer-string) (encode-coding-string json 'utf-8)))
+            (should (eobp)))
+          (should (equal (json-parse-string json) lisp))
+          (with-temp-buffer
+            (insert json)
+            (goto-char 1)
+            (should (equal (json-parse-buffer) lisp))
+            (should (eobp)))
+          (with-temp-buffer
+            (set-buffer-multibyte nil)
+            (insert (encode-coding-string json 'utf-8))
+            (goto-char 1)
+            (should (equal (json-parse-buffer) lisp))
+            (should (eobp))))))))
 
 (ert-deftest json-serialize/object ()
   (let ((table (make-hash-table :test #'equal)))
@@ -226,7 +227,8 @@
   (should (equal (json-serialize ["foo"]) "[\"foo\"]"))
   (should (equal (json-serialize ["a\n\fb"]) "[\"a\\n\\fb\"]"))
   (should (equal (json-serialize ["\nasdфыв\u001f\u007ffgh\t"])
-                 "[\"\\nasdфыв\\u001F\u007ffgh\\t\"]"))
+                 (encode-coding-string "[\"\\nasdфыв\\u001F\u007ffgh\\t\"]"
+                                       'utf-8)))
   (should (equal (json-serialize ["a\0b"]) "[\"a\\u0000b\"]"))
   (should-error (json-serialize ["\xC3\x84"]))
   (should-error (json-serialize ["\u00C4\xC3\x84"])))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]