]> git.eshelyaron.com Git - emacs.git/commitdiff
Make json-serialize always return a unibyte string (bug#70007)
authorMattias Engdegård <mattiase@acm.org>
Sun, 8 Sep 2024 18:02:34 +0000 (20:02 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sat, 14 Sep 2024 20:15:07 +0000 (22:15 +0200)
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.

(cherry picked from commit e55e2e1c6baebbd105f930fa553ec65c74a3000d)

doc/lispref/text.texi
src/json.c
test/src/json-tests.el

index 03b2c3b2b6d1cdef9b911230b3e904a2a3d3db90..a2a429e188265b72e0fca87fccd9dead6e142cd9 100644 (file)
@@ -5852,7 +5852,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:
 
index 21066d213280ddf9bfb40149054daa656cfedc7e..41566f8369bb2720af11299869cea65c4e94fe80 100644 (file)
@@ -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,
index ebac70fb1c7e19d55ed5f4aebb75fef90b6a8feb..1d7491a4593408124f41fe2c5ce0d9227e271488 100644 (file)
@@ -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)
                    "\"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)))
   (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"])))