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.
This commit is contained in:
parent
89c99891b2
commit
e55e2e1c6b
4 changed files with 36 additions and 37 deletions
|
@ -5844,7 +5844,7 @@ can be serialized to JSON@. Likewise, the parsing functions will
|
||||||
return any of the possible types described above.
|
return any of the possible types described above.
|
||||||
|
|
||||||
@defun json-serialize object &rest args
|
@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
|
representation of @var{object}. The argument @var{args} is a list of
|
||||||
keyword/argument pairs. The following keywords are accepted:
|
keyword/argument pairs. The following keywords are accepted:
|
||||||
|
|
||||||
|
|
7
etc/NEWS
7
etc/NEWS
|
@ -3071,6 +3071,13 @@ entire SQL file.
|
||||||
|
|
||||||
** JSON
|
** 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.
|
*** 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
|
A JSON object such as '{"a":1,"a":2}' will now be translated into the
|
||||||
|
|
14
src/json.c
14
src/json.c
|
@ -559,16 +559,6 @@ json_out_something (json_out_t *jo, Lisp_Object obj)
|
||||||
wrong_type_argument (Qjson_value_p, 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
|
static void
|
||||||
json_serialize (json_out_t *jo, Lisp_Object object,
|
json_serialize (json_out_t *jo, Lisp_Object object,
|
||||||
ptrdiff_t nargs, Lisp_Object *args)
|
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,
|
DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, MANY,
|
||||||
NULL,
|
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:
|
OBJECT is translated as follows:
|
||||||
|
|
||||||
|
@ -629,7 +619,7 @@ usage: (json-serialize OBJECT &rest ARGS) */)
|
||||||
specpdl_ref count = SPECPDL_INDEX ();
|
specpdl_ref count = SPECPDL_INDEX ();
|
||||||
json_out_t jo;
|
json_out_t jo;
|
||||||
json_serialize (&jo, args[0], nargs - 1, args + 1);
|
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,
|
DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, MANY,
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
(json
|
(json
|
||||||
"[null,false,true,0,123,-456,3.75,\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"]")
|
"[null,false,true,0,123,-456,3.75,\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"]")
|
||||||
(json-bytes (encode-coding-string json 'utf-8)))
|
(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
|
(with-temp-buffer
|
||||||
;; multibyte buffer
|
;; multibyte buffer
|
||||||
(json-insert lisp)
|
(json-insert lisp)
|
||||||
|
@ -82,7 +82,8 @@
|
||||||
"\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
|
"\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
|
||||||
(cl-destructuring-bind (lisp json) case
|
(cl-destructuring-bind (lisp json) case
|
||||||
(ert-info ((format "%S ↔ %S" lisp json))
|
(ert-info ((format "%S ↔ %S" lisp json))
|
||||||
(should (equal (json-serialize lisp) json))
|
(let ((json-bytes (encode-coding-string json 'utf-8)))
|
||||||
|
(should (equal (json-serialize lisp) json-bytes))
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
(json-insert lisp)
|
(json-insert lisp)
|
||||||
(should (equal (buffer-string) json))
|
(should (equal (buffer-string) json))
|
||||||
|
@ -103,7 +104,7 @@
|
||||||
(insert (encode-coding-string json 'utf-8))
|
(insert (encode-coding-string json 'utf-8))
|
||||||
(goto-char 1)
|
(goto-char 1)
|
||||||
(should (equal (json-parse-buffer) lisp))
|
(should (equal (json-parse-buffer) lisp))
|
||||||
(should (eobp)))))))
|
(should (eobp))))))))
|
||||||
|
|
||||||
(ert-deftest json-serialize/object ()
|
(ert-deftest json-serialize/object ()
|
||||||
(let ((table (make-hash-table :test #'equal)))
|
(let ((table (make-hash-table :test #'equal)))
|
||||||
|
@ -226,7 +227,8 @@
|
||||||
(should (equal (json-serialize ["foo"]) "[\"foo\"]"))
|
(should (equal (json-serialize ["foo"]) "[\"foo\"]"))
|
||||||
(should (equal (json-serialize ["a\n\fb"]) "[\"a\\n\\fb\"]"))
|
(should (equal (json-serialize ["a\n\fb"]) "[\"a\\n\\fb\"]"))
|
||||||
(should (equal (json-serialize ["\nasdфыв\u001f\u007ffgh\t"])
|
(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 (equal (json-serialize ["a\0b"]) "[\"a\\u0000b\"]"))
|
||||||
(should-error (json-serialize ["\xC3\x84"]))
|
(should-error (json-serialize ["\xC3\x84"]))
|
||||||
(should-error (json-serialize ["\u00C4\xC3\x84"])))
|
(should-error (json-serialize ["\u00C4\xC3\x84"])))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue