Add JSON_ENCODE_ANY flag to allow encoding any JSON value

Closes GH-19.
This commit is contained in:
Petri Lehtinen 2011-05-14 12:56:14 +03:00
parent c3492973e1
commit 636d5f60f9
4 changed files with 78 additions and 9 deletions

View File

@ -680,8 +680,10 @@ Encoding
======== ========
This sections describes the functions that can be used to encode This sections describes the functions that can be used to encode
values to JSON. Only objects and arrays can be encoded, since they are values to JSON. By default, only objects and arrays can be encoded
the only valid "root" values of a JSON text. directly, since they are the only valid *root* values of a JSON text.
To encode any JSON value, use the ``JSON_ENCODE_ANY`` flag (see
below).
By default, the output has no newlines, and spaces are used between By default, the output has no newlines, and spaces are used between
array and object elements for a readable output. This behavior can be array and object elements for a readable output. This behavior can be
@ -722,6 +724,17 @@ can be ORed together to obtain *flags*.
example, decoding a JSON text and then encoding with this flag example, decoding a JSON text and then encoding with this flag
preserves the order of object keys. preserves the order of object keys.
``JSON_ENCODE_ANY``
Specifying this flag makes it possible to encode any JSON value on
its own. Without it, only objects and arrays can be passed as the
*root* value to the encoding functions.
**Note:** Encoding any value may be useful in some scenarios, but
it's generally discouraged as it violates strict compatiblity with
:rfc:`4627`. If you use this flag, don't expect interoperatibility
with other JSON systems. Even Jansson itself doesn't have any means
to decode JSON texts whose root value is not object or array.
The following functions perform the actual JSON encoding. The result The following functions perform the actual JSON encoding. The result
is in UTF-8. is in UTF-8.

View File

@ -421,8 +421,10 @@ char *json_dumps(const json_t *json, size_t flags)
strbuffer_t strbuff; strbuffer_t strbuff;
char *result; char *result;
if(!json_is_array(json) && !json_is_object(json)) if(!(flags & JSON_ENCODE_ANY)) {
return NULL; if(!json_is_array(json) && !json_is_object(json))
return NULL;
}
if(strbuffer_init(&strbuff)) if(strbuffer_init(&strbuff))
return NULL; return NULL;
@ -440,8 +442,10 @@ char *json_dumps(const json_t *json, size_t flags)
int json_dumpf(const json_t *json, FILE *output, size_t flags) int json_dumpf(const json_t *json, FILE *output, size_t flags)
{ {
if(!json_is_array(json) && !json_is_object(json)) if(!(flags & JSON_ENCODE_ANY)) {
return -1; if(!json_is_array(json) && !json_is_object(json))
return -1;
}
return do_dump(json, flags, 0, dump_to_file, (void *)output); return do_dump(json, flags, 0, dump_to_file, (void *)output);
} }

View File

@ -226,6 +226,7 @@ json_t *json_load_file(const char *path, size_t flags, json_error_t *error);
#define JSON_ENSURE_ASCII 0x40 #define JSON_ENSURE_ASCII 0x40
#define JSON_SORT_KEYS 0x80 #define JSON_SORT_KEYS 0x80
#define JSON_PRESERVE_ORDER 0x100 #define JSON_PRESERVE_ORDER 0x100
#define JSON_ENCODE_ANY 0x200
char *json_dumps(const json_t *json, size_t flags); char *json_dumps(const json_t *json, size_t flags);
int json_dumpf(const json_t *json, FILE *output, size_t flags); int json_dumpf(const json_t *json, FILE *output, size_t flags);

View File

@ -9,13 +9,13 @@
#include <string.h> #include <string.h>
#include "util.h" #include "util.h"
int main() static void encode_twice()
{ {
/* Encode an empty object/array, add an item, encode again */
json_t *json; json_t *json;
char *result; char *result;
/* Encode an empty object/array, add an item, encode again */
json = json_object(); json = json_object();
result = json_dumps(json, 0); result = json_dumps(json, 0);
if(!result || strcmp(result, "{}")) if(!result || strcmp(result, "{}"))
@ -43,7 +43,10 @@ int main()
free(result); free(result);
json_decref(json); json_decref(json);
}
static void circular_references()
{
/* Construct a JSON object/array with a circular reference: /* Construct a JSON object/array with a circular reference:
object: {"a": {"b": {"c": <circular reference to $.a>}}} object: {"a": {"b": {"c": <circular reference to $.a>}}}
@ -51,6 +54,10 @@ int main()
Encode it, remove the circular reference and encode again. Encode it, remove the circular reference and encode again.
*/ */
json_t *json;
char *result;
json = json_object(); json = json_object();
json_object_set_new(json, "a", json_object()); json_object_set_new(json, "a", json_object());
json_object_set_new(json_object_get(json, "a"), "b", json_object()); json_object_set_new(json_object_get(json, "a"), "b", json_object());
@ -86,6 +93,50 @@ int main()
free(result); free(result);
json_decref(json); json_decref(json);
}
static void encode_other_than_array_or_object()
{
/* Encoding anything other than array or object should only
* succeed if the JSON_ENCODE_ANY flag is used */
json_t *json;
FILE *fp = NULL;
char *result;
json = json_string("foo");
if(json_dumps(json, 0) != NULL)
fail("json_dumps encoded a string!");
if(json_dumpf(json, fp, 0) == 0)
fail("json_dumpf encoded a string!");
result = json_dumps(json, JSON_ENCODE_ANY);
if(!result || strcmp(result, "\"foo\"") != 0)
fail("json_dumps failed to encode a string with JSON_ENCODE_ANY");
free(result);
json_decref(json);
json = json_integer(42);
if(json_dumps(json, 0) != NULL)
fail("json_dumps encoded an integer!");
if(json_dumpf(json, fp, 0) == 0)
fail("json_dumpf encoded an integer!");
result = json_dumps(json, JSON_ENCODE_ANY);
if(!result || strcmp(result, "42") != 0)
fail("json_dumps failed to encode an integer with JSON_ENCODE_ANY");
free(result);
json_decref(json);
}
int main()
{
encode_twice();
circular_references();
encode_other_than_array_or_object();
return 0; return 0;
} }