summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Távora <joaotavora@gmail.com>2018-05-30 02:48:31 +0100
committerJoão Távora <joaotavora@gmail.com>2018-05-30 02:53:19 +0100
commit506d38434b54a3999163a78c91fb06a524a5cad2 (patch)
treedfd7846f020cc41c5863b2af567856107b90cc9d
parent224f8ea95f00cc60ee77aeaad6585bb2ef845f70 (diff)
downloademacs-scratch/support-plists-in-jsonc.tar.gz
Instead of a json-serialize-use-plists global, use function argsscratch/support-plists-in-jsonc
* src/json.c (syms_of_json): Don't defive json-serialize-use-plists (Fjson_insert, lisp_to_json, list_to_json_toplevel_1) (list_to_json_toplevel, Fjson_serialize): Use and pass around use_plists arg. * doc/lispref/text.texi: (Parsing JSON): json-serialize and json-insert now have a USE-PLISTS arg. * test/src/json-tests.el (json-serialize/object): Use json-serialize's USE-PLISTS arg.
-rw-r--r--doc/lispref/text.texi15
-rw-r--r--src/json.c66
-rw-r--r--test/src/json-tests.el21
3 files changed, 49 insertions, 53 deletions
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 3995102237a..d2371d61811 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -5067,22 +5067,19 @@ either @code{hash-table} to parse JSON objects as hashtables with
string keys (the default), @code{alist} to parse them as alists or
@code{plist} to parse them as plists.
-@vindex json-serialize-use-plists
@cindex serializing plists as json
- For the serialization function, the variable
-@var{json-serialize-use-plists} controls the converse process,
-resolving the ambiguity when a list is found in the Lisp object to
-serialize. If @code{nil}, its default, the list is interpreted as an
-alist, otherwise it is interpreted as a plist.
-
@defun json-serialize object
This function returns a new Lisp string which contains the JSON
-representation of @var{object}.
+representation of @var{object}. The optional argument @var{use-plists}
+resolves the ambiguity when a list is found in the Lisp object to
+serialize: if it is @code{nil}, its default, the list is interpreted
+as an alist, otherwise it is interpreted as a plist.
@end defun
@defun json-insert object
This function inserts the JSON representation of @var{object} into the
-current buffer before point.
+current buffer before point. The optional argument @var{use-plists} is
+interpreted as in @dfn{json-serialize}.
@end defun
@defun json-parse-string string &key (object-type @code{hash-table})
diff --git a/src/json.c b/src/json.c
index ccd58c047e5..8318b637e05 100644
--- a/src/json.c
+++ b/src/json.c
@@ -325,14 +325,14 @@ json_check_utf8 (Lisp_Object string)
CHECK_TYPE (utf8_string_p (string), Qutf_8_string_p, string);
}
-static json_t *lisp_to_json (Lisp_Object);
+static json_t *lisp_to_json (Lisp_Object, Lisp_Object);
/* Convert a Lisp object to a toplevel JSON object (array or object).
This returns Lisp_Object so we can use unbind_to. The return value
is always nil. */
static _GL_ARG_NONNULL ((2)) Lisp_Object
-lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
+lisp_to_json_toplevel_1 (Lisp_Object lisp, Lisp_Object use_plists, json_t **json)
{
if (VECTORP (lisp))
{
@@ -343,7 +343,8 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
for (ptrdiff_t i = 0; i < size; ++i)
{
int status
- = json_array_append_new (*json, lisp_to_json (AREF (lisp, i)));
+ = json_array_append_new (*json, lisp_to_json (AREF (lisp, i),
+ use_plists));
if (status == -1)
json_out_of_memory ();
}
@@ -370,7 +371,8 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
if (json_object_get (*json, key_str) != NULL)
wrong_type_argument (Qjson_value_p, lisp);
int status = json_object_set_new (*json, key_str,
- lisp_to_json (HASH_VALUE (h, i)));
+ lisp_to_json (HASH_VALUE (h, i),
+ use_plists));
if (status == -1)
{
/* A failure can be caused either by an invalid key or
@@ -398,7 +400,7 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
const char *key_str;
Lisp_Object value;
Lisp_Object key_symbol;
- if ( EQ (Vjson_serialize_use_plists, Qt) ) {
+ if ( EQ (use_plists, Qt) ) {
key_symbol = XCAR (tail);
tail = XCDR(tail);
CHECK_CONS (tail);
@@ -417,14 +419,15 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
check_string_without_embedded_nulls (key);
key_str = SSDATA (key);
/* If using plists, maybe strip the ":" from symbol-name */
- if (EQ (Vjson_serialize_use_plists, Qt) &&
+ if (EQ (use_plists, Qt) &&
':' == key_str[0] &&
key_str[1] ) key_str = &key_str[1];
/* Only add element if key is not already present. */
if (json_object_get (*json, key_str) == NULL)
{
int status
- = json_object_set_new (*json, key_str, lisp_to_json (value));
+ = json_object_set_new (*json, key_str,
+ lisp_to_json (value, use_plists));
if (status == -1)
json_out_of_memory ();
}
@@ -441,12 +444,12 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json)
hashtable, or alist. */
static json_t *
-lisp_to_json_toplevel (Lisp_Object lisp)
+lisp_to_json_toplevel (Lisp_Object lisp, Lisp_Object use_plists)
{
if (++lisp_eval_depth > max_lisp_eval_depth)
xsignal0 (Qjson_object_too_deep);
json_t *json;
- lisp_to_json_toplevel_1 (lisp, &json);
+ lisp_to_json_toplevel_1 (lisp, use_plists, &json);
--lisp_eval_depth;
return json;
}
@@ -456,7 +459,7 @@ lisp_to_json_toplevel (Lisp_Object lisp)
JSON object. */
static json_t *
-lisp_to_json (Lisp_Object lisp)
+lisp_to_json (Lisp_Object lisp, Lisp_Object use_plists)
{
if (EQ (lisp, QCnull))
return json_check (json_null ());
@@ -486,24 +489,26 @@ lisp_to_json (Lisp_Object lisp)
}
/* LISP now must be a vector, hashtable, or alist. */
- return lisp_to_json_toplevel (lisp);
+ return lisp_to_json_toplevel (lisp, use_plists);
}
-DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, 1, NULL,
+DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, 2, NULL,
doc: /* Return the JSON representation of OBJECT as a string.
OBJECT must be a vector of values or a key-value map. Hashtables,
-alists and plists are accepted as maps, the variable
-`json-serialize-use-plists' controlling which one of the latter two to
-use. In any of these cases, values can be `:null', `:false', t,
-numbers, strings, or, recursively, other vectors, hashtables, alists
-or plists. `:null', `:false', and t will be converted to JSON null,
-false, and true values, respectively. Vectors will be converted to
-JSON arrays, and hashtables, alists and plists to JSON objects.
-Hashtable keys must be strings without embedded null characters and
-must be unique within each object. Alist or plist keys must be
-symbols; if a key is duplicate, the first instance is used. */)
- (Lisp_Object object)
+alists and plists are accepted as maps. Since the latter two are both
+lists and this function can't currently guess the format from the
+variable, the optional argument USE-PLISTS is used to control which of
+the two to use. In any of these cases, values can be `:null',
+`:false', t, numbers, strings, or, recursively, other vectors,
+hashtables, alists or plists. `:null', `:false', and t will be
+converted to JSON null, false, and true values, respectively. Vectors
+will be converted to JSON arrays, and hashtables, alists and plists to
+JSON objects. Hashtable keys must be strings without embedded null
+characters and must be unique within each object. Alist or plist keys
+must be symbols; if a key is duplicate, the first instance is
+used. */)
+ (Lisp_Object object, Lisp_Object use_plists)
{
ptrdiff_t count = SPECPDL_INDEX ();
@@ -522,7 +527,7 @@ symbols; if a key is duplicate, the first instance is used. */)
}
#endif
- json_t *json = lisp_to_json_toplevel (object);
+ json_t *json = lisp_to_json_toplevel (object, use_plists);
record_unwind_protect_ptr (json_release_object, json);
/* If desired, we might want to add the following flags:
@@ -578,12 +583,12 @@ json_insert_callback (const char *buffer, size_t size, void *data)
return NILP (d->error) ? 0 : -1;
}
-DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, 1, NULL,
+DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, 2, NULL,
doc: /* Insert the JSON representation of OBJECT before point.
This is the same as (insert (json-serialize OBJECT)), but potentially
faster. See the function `json-serialize' for allowed values of
-OBJECT. */)
- (Lisp_Object object)
+OBJECT and the meaning of USE-PLISTS */)
+ (Lisp_Object object, Lisp_Object use_plists)
{
ptrdiff_t count = SPECPDL_INDEX ();
@@ -602,7 +607,7 @@ OBJECT. */)
}
#endif
- json_t *json = lisp_to_json (object);
+ json_t *json = lisp_to_json (object, use_plists);
record_unwind_protect_ptr (json_release_object, json);
struct json_insert_data data;
@@ -950,11 +955,6 @@ syms_of_json (void)
DEFSYM (Qpure, "pure");
DEFSYM (Qside_effect_free, "side-effect-free");
- DEFVAR_LISP ("json-serialize-use-plists", Vjson_serialize_use_plists,
- doc:
- /* If non-nil use plists instead of alists in json-serialize.*/);
- Vjson_serialize_use_plists = Qnil;
-
DEFSYM (Qjson_serialize, "json-serialize");
DEFSYM (Qjson_parse_string, "json-parse-string");
Fput (Qjson_serialize, Qpure, Qt);
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
index 5c9be20e957..b7c17a4cf10 100644
--- a/test/src/json-tests.el
+++ b/test/src/json-tests.el
@@ -71,17 +71,16 @@
(should-error (json-serialize '#1=((a . 1) . #1#)) :type 'circular-list)
(should-error (json-serialize '(#1=(a #1#))))
- (let ((json-serialize-use-plists t))
- (should (equal (json-serialize '(:abc [1 2 t] :def :null))
- "{\"abc\":[1,2,true],\"def\":null}"))
- (should (equal (json-serialize '(abc [1 2 t] :def :null))
- "{\"abc\":[1,2,true],\"def\":null}"))
- (should-error (json-serialize '#1=(:a 1 . #1#)) :type 'circular-list)
- (should-error (json-serialize '((abc . 1))) :type 'wrong-type-argument)
- (should-error (json-serialize '(:foo bar (abc . 1)))
- :type 'wrong-type-argument)
- (should-error (json-serialize '(:foo bar :odd-numbered))
- :type 'wrong-type-argument)))
+ (should (equal (json-serialize '(:abc [1 2 t] :def :null) t)
+ "{\"abc\":[1,2,true],\"def\":null}"))
+ (should (equal (json-serialize '(abc [1 2 t] :def :null) t)
+ "{\"abc\":[1,2,true],\"def\":null}"))
+ (should-error (json-serialize '#1=(:a 1 . #1#) t) :type 'circular-list)
+ (should-error (json-serialize '((abc . 1)) t) :type 'wrong-type-argument)
+ (should-error (json-serialize '(:foo bar (abc . 1)) t)
+ :type 'wrong-type-argument)
+ (should-error (json-serialize '(:foo bar :odd-numbered) t)
+ :type 'wrong-type-argument))
(ert-deftest json-serialize/object-with-duplicate-keys ()
(skip-unless (fboundp 'json-serialize))