Add JSON_ENCODE_ANY flag to allow encoding any JSON value
authorPetri Lehtinen <petri@digip.org>
Sat, 14 May 2011 09:56:14 +0000 (12:56 +0300)
committerPetri Lehtinen <petri@digip.org>
Sat, 14 May 2011 09:57:12 +0000 (12:57 +0300)
Closes GH-19.

doc/apiref.rst
src/dump.c
src/jansson.h
test/suites/api/test_dump.c

index 991ee5a..6dfe839 100644 (file)
@@ -680,8 +680,10 @@ Encoding
 ========
 
 This sections describes the functions that can be used to encode
-values to JSON. Only objects and arrays can be encoded, since they are
-the only valid "root" values of a JSON text.
+values to JSON. By default, only objects and arrays can be encoded
+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
 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
    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
 is in UTF-8.
 
index 9c01366..f32f667 100644 (file)
@@ -421,8 +421,10 @@ char *json_dumps(const json_t *json, size_t flags)
     strbuffer_t strbuff;
     char *result;
 
-    if(!json_is_array(json) && !json_is_object(json))
-        return NULL;
+    if(!(flags & JSON_ENCODE_ANY)) {
+        if(!json_is_array(json) && !json_is_object(json))
+           return NULL;
+    }
 
     if(strbuffer_init(&strbuff))
         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)
 {
-    if(!json_is_array(json) && !json_is_object(json))
-        return -1;
+    if(!(flags & JSON_ENCODE_ANY)) {
+        if(!json_is_array(json) && !json_is_object(json))
+           return -1;
+    }
 
     return do_dump(json, flags, 0, dump_to_file, (void *)output);
 }
index 03e9d5a..2a0860e 100644 (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_SORT_KEYS      0x80
 #define JSON_PRESERVE_ORDER 0x100
+#define JSON_ENCODE_ANY     0x200
 
 char *json_dumps(const json_t *json, size_t flags);
 int json_dumpf(const json_t *json, FILE *output, size_t flags);
index 363dd10..17d588b 100644 (file)
@@ -9,13 +9,13 @@
 #include <string.h>
 #include "util.h"
 
-int main()
+static void encode_twice()
 {
+    /* Encode an empty object/array, add an item, encode again */
+
     json_t *json;
     char *result;
 
-    /* Encode an empty object/array, add an item, encode again */
-
     json = json_object();
     result = json_dumps(json, 0);
     if(!result || strcmp(result, "{}"))
@@ -43,7 +43,10 @@ int main()
     free(result);
 
     json_decref(json);
+}
 
+static void circular_references()
+{
     /* Construct a JSON object/array with a circular reference:
 
        object: {"a": {"b": {"c": <circular reference to $.a>}}}
@@ -51,6 +54,10 @@ int main()
 
        Encode it, remove the circular reference and encode again.
     */
+
+    json_t *json;
+    char *result;
+
     json = json_object();
     json_object_set_new(json, "a", json_object());
     json_object_set_new(json_object_get(json, "a"), "b", json_object());
@@ -86,6 +93,50 @@ int main()
     free(result);
 
     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;
 }