diff options
Diffstat (limited to 'src/json.c')
| -rw-r--r-- | src/json.c | 66 |
1 files changed, 33 insertions, 33 deletions
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) | |||
| 325 | CHECK_TYPE (utf8_string_p (string), Qutf_8_string_p, string); | 325 | CHECK_TYPE (utf8_string_p (string), Qutf_8_string_p, string); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | static json_t *lisp_to_json (Lisp_Object); | 328 | static json_t *lisp_to_json (Lisp_Object, Lisp_Object); |
| 329 | 329 | ||
| 330 | /* Convert a Lisp object to a toplevel JSON object (array or object). | 330 | /* Convert a Lisp object to a toplevel JSON object (array or object). |
| 331 | This returns Lisp_Object so we can use unbind_to. The return value | 331 | This returns Lisp_Object so we can use unbind_to. The return value |
| 332 | is always nil. */ | 332 | is always nil. */ |
| 333 | 333 | ||
| 334 | static _GL_ARG_NONNULL ((2)) Lisp_Object | 334 | static _GL_ARG_NONNULL ((2)) Lisp_Object |
| 335 | lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json) | 335 | lisp_to_json_toplevel_1 (Lisp_Object lisp, Lisp_Object use_plists, json_t **json) |
| 336 | { | 336 | { |
| 337 | if (VECTORP (lisp)) | 337 | if (VECTORP (lisp)) |
| 338 | { | 338 | { |
| @@ -343,7 +343,8 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json) | |||
| 343 | for (ptrdiff_t i = 0; i < size; ++i) | 343 | for (ptrdiff_t i = 0; i < size; ++i) |
| 344 | { | 344 | { |
| 345 | int status | 345 | int status |
| 346 | = json_array_append_new (*json, lisp_to_json (AREF (lisp, i))); | 346 | = json_array_append_new (*json, lisp_to_json (AREF (lisp, i), |
| 347 | use_plists)); | ||
| 347 | if (status == -1) | 348 | if (status == -1) |
| 348 | json_out_of_memory (); | 349 | json_out_of_memory (); |
| 349 | } | 350 | } |
| @@ -370,7 +371,8 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json) | |||
| 370 | if (json_object_get (*json, key_str) != NULL) | 371 | if (json_object_get (*json, key_str) != NULL) |
| 371 | wrong_type_argument (Qjson_value_p, lisp); | 372 | wrong_type_argument (Qjson_value_p, lisp); |
| 372 | int status = json_object_set_new (*json, key_str, | 373 | int status = json_object_set_new (*json, key_str, |
| 373 | lisp_to_json (HASH_VALUE (h, i))); | 374 | lisp_to_json (HASH_VALUE (h, i), |
| 375 | use_plists)); | ||
| 374 | if (status == -1) | 376 | if (status == -1) |
| 375 | { | 377 | { |
| 376 | /* A failure can be caused either by an invalid key or | 378 | /* 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) | |||
| 398 | const char *key_str; | 400 | const char *key_str; |
| 399 | Lisp_Object value; | 401 | Lisp_Object value; |
| 400 | Lisp_Object key_symbol; | 402 | Lisp_Object key_symbol; |
| 401 | if ( EQ (Vjson_serialize_use_plists, Qt) ) { | 403 | if ( EQ (use_plists, Qt) ) { |
| 402 | key_symbol = XCAR (tail); | 404 | key_symbol = XCAR (tail); |
| 403 | tail = XCDR(tail); | 405 | tail = XCDR(tail); |
| 404 | CHECK_CONS (tail); | 406 | CHECK_CONS (tail); |
| @@ -417,14 +419,15 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json) | |||
| 417 | check_string_without_embedded_nulls (key); | 419 | check_string_without_embedded_nulls (key); |
| 418 | key_str = SSDATA (key); | 420 | key_str = SSDATA (key); |
| 419 | /* If using plists, maybe strip the ":" from symbol-name */ | 421 | /* If using plists, maybe strip the ":" from symbol-name */ |
| 420 | if (EQ (Vjson_serialize_use_plists, Qt) && | 422 | if (EQ (use_plists, Qt) && |
| 421 | ':' == key_str[0] && | 423 | ':' == key_str[0] && |
| 422 | key_str[1] ) key_str = &key_str[1]; | 424 | key_str[1] ) key_str = &key_str[1]; |
| 423 | /* Only add element if key is not already present. */ | 425 | /* Only add element if key is not already present. */ |
| 424 | if (json_object_get (*json, key_str) == NULL) | 426 | if (json_object_get (*json, key_str) == NULL) |
| 425 | { | 427 | { |
| 426 | int status | 428 | int status |
| 427 | = json_object_set_new (*json, key_str, lisp_to_json (value)); | 429 | = json_object_set_new (*json, key_str, |
| 430 | lisp_to_json (value, use_plists)); | ||
| 428 | if (status == -1) | 431 | if (status == -1) |
| 429 | json_out_of_memory (); | 432 | json_out_of_memory (); |
| 430 | } | 433 | } |
| @@ -441,12 +444,12 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json) | |||
| 441 | hashtable, or alist. */ | 444 | hashtable, or alist. */ |
| 442 | 445 | ||
| 443 | static json_t * | 446 | static json_t * |
| 444 | lisp_to_json_toplevel (Lisp_Object lisp) | 447 | lisp_to_json_toplevel (Lisp_Object lisp, Lisp_Object use_plists) |
| 445 | { | 448 | { |
| 446 | if (++lisp_eval_depth > max_lisp_eval_depth) | 449 | if (++lisp_eval_depth > max_lisp_eval_depth) |
| 447 | xsignal0 (Qjson_object_too_deep); | 450 | xsignal0 (Qjson_object_too_deep); |
| 448 | json_t *json; | 451 | json_t *json; |
| 449 | lisp_to_json_toplevel_1 (lisp, &json); | 452 | lisp_to_json_toplevel_1 (lisp, use_plists, &json); |
| 450 | --lisp_eval_depth; | 453 | --lisp_eval_depth; |
| 451 | return json; | 454 | return json; |
| 452 | } | 455 | } |
| @@ -456,7 +459,7 @@ lisp_to_json_toplevel (Lisp_Object lisp) | |||
| 456 | JSON object. */ | 459 | JSON object. */ |
| 457 | 460 | ||
| 458 | static json_t * | 461 | static json_t * |
| 459 | lisp_to_json (Lisp_Object lisp) | 462 | lisp_to_json (Lisp_Object lisp, Lisp_Object use_plists) |
| 460 | { | 463 | { |
| 461 | if (EQ (lisp, QCnull)) | 464 | if (EQ (lisp, QCnull)) |
| 462 | return json_check (json_null ()); | 465 | return json_check (json_null ()); |
| @@ -486,24 +489,26 @@ lisp_to_json (Lisp_Object lisp) | |||
| 486 | } | 489 | } |
| 487 | 490 | ||
| 488 | /* LISP now must be a vector, hashtable, or alist. */ | 491 | /* LISP now must be a vector, hashtable, or alist. */ |
| 489 | return lisp_to_json_toplevel (lisp); | 492 | return lisp_to_json_toplevel (lisp, use_plists); |
| 490 | } | 493 | } |
| 491 | 494 | ||
| 492 | DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, 1, NULL, | 495 | DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, 2, NULL, |
| 493 | doc: /* Return the JSON representation of OBJECT as a string. | 496 | doc: /* Return the JSON representation of OBJECT as a string. |
| 494 | 497 | ||
| 495 | OBJECT must be a vector of values or a key-value map. Hashtables, | 498 | OBJECT must be a vector of values or a key-value map. Hashtables, |
| 496 | alists and plists are accepted as maps, the variable | 499 | alists and plists are accepted as maps. Since the latter two are both |
| 497 | `json-serialize-use-plists' controlling which one of the latter two to | 500 | lists and this function can't currently guess the format from the |
| 498 | use. In any of these cases, values can be `:null', `:false', t, | 501 | variable, the optional argument USE-PLISTS is used to control which of |
| 499 | numbers, strings, or, recursively, other vectors, hashtables, alists | 502 | the two to use. In any of these cases, values can be `:null', |
| 500 | or plists. `:null', `:false', and t will be converted to JSON null, | 503 | `:false', t, numbers, strings, or, recursively, other vectors, |
| 501 | false, and true values, respectively. Vectors will be converted to | 504 | hashtables, alists or plists. `:null', `:false', and t will be |
| 502 | JSON arrays, and hashtables, alists and plists to JSON objects. | 505 | converted to JSON null, false, and true values, respectively. Vectors |
| 503 | Hashtable keys must be strings without embedded null characters and | 506 | will be converted to JSON arrays, and hashtables, alists and plists to |
| 504 | must be unique within each object. Alist or plist keys must be | 507 | JSON objects. Hashtable keys must be strings without embedded null |
| 505 | symbols; if a key is duplicate, the first instance is used. */) | 508 | characters and must be unique within each object. Alist or plist keys |
| 506 | (Lisp_Object object) | 509 | must be symbols; if a key is duplicate, the first instance is |
| 510 | used. */) | ||
| 511 | (Lisp_Object object, Lisp_Object use_plists) | ||
| 507 | { | 512 | { |
| 508 | ptrdiff_t count = SPECPDL_INDEX (); | 513 | ptrdiff_t count = SPECPDL_INDEX (); |
| 509 | 514 | ||
| @@ -522,7 +527,7 @@ symbols; if a key is duplicate, the first instance is used. */) | |||
| 522 | } | 527 | } |
| 523 | #endif | 528 | #endif |
| 524 | 529 | ||
| 525 | json_t *json = lisp_to_json_toplevel (object); | 530 | json_t *json = lisp_to_json_toplevel (object, use_plists); |
| 526 | record_unwind_protect_ptr (json_release_object, json); | 531 | record_unwind_protect_ptr (json_release_object, json); |
| 527 | 532 | ||
| 528 | /* If desired, we might want to add the following flags: | 533 | /* 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) | |||
| 578 | return NILP (d->error) ? 0 : -1; | 583 | return NILP (d->error) ? 0 : -1; |
| 579 | } | 584 | } |
| 580 | 585 | ||
| 581 | DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, 1, NULL, | 586 | DEFUN ("json-insert", Fjson_insert, Sjson_insert, 1, 2, NULL, |
| 582 | doc: /* Insert the JSON representation of OBJECT before point. | 587 | doc: /* Insert the JSON representation of OBJECT before point. |
| 583 | This is the same as (insert (json-serialize OBJECT)), but potentially | 588 | This is the same as (insert (json-serialize OBJECT)), but potentially |
| 584 | faster. See the function `json-serialize' for allowed values of | 589 | faster. See the function `json-serialize' for allowed values of |
| 585 | OBJECT. */) | 590 | OBJECT and the meaning of USE-PLISTS */) |
| 586 | (Lisp_Object object) | 591 | (Lisp_Object object, Lisp_Object use_plists) |
| 587 | { | 592 | { |
| 588 | ptrdiff_t count = SPECPDL_INDEX (); | 593 | ptrdiff_t count = SPECPDL_INDEX (); |
| 589 | 594 | ||
| @@ -602,7 +607,7 @@ OBJECT. */) | |||
| 602 | } | 607 | } |
| 603 | #endif | 608 | #endif |
| 604 | 609 | ||
| 605 | json_t *json = lisp_to_json (object); | 610 | json_t *json = lisp_to_json (object, use_plists); |
| 606 | record_unwind_protect_ptr (json_release_object, json); | 611 | record_unwind_protect_ptr (json_release_object, json); |
| 607 | 612 | ||
| 608 | struct json_insert_data data; | 613 | struct json_insert_data data; |
| @@ -950,11 +955,6 @@ syms_of_json (void) | |||
| 950 | DEFSYM (Qpure, "pure"); | 955 | DEFSYM (Qpure, "pure"); |
| 951 | DEFSYM (Qside_effect_free, "side-effect-free"); | 956 | DEFSYM (Qside_effect_free, "side-effect-free"); |
| 952 | 957 | ||
| 953 | DEFVAR_LISP ("json-serialize-use-plists", Vjson_serialize_use_plists, | ||
| 954 | doc: | ||
| 955 | /* If non-nil use plists instead of alists in json-serialize.*/); | ||
| 956 | Vjson_serialize_use_plists = Qnil; | ||
| 957 | |||
| 958 | DEFSYM (Qjson_serialize, "json-serialize"); | 958 | DEFSYM (Qjson_serialize, "json-serialize"); |
| 959 | DEFSYM (Qjson_parse_string, "json-parse-string"); | 959 | DEFSYM (Qjson_parse_string, "json-parse-string"); |
| 960 | Fput (Qjson_serialize, Qpure, Qt); | 960 | Fput (Qjson_serialize, Qpure, Qt); |