From: Petri Lehtinen Date: Wed, 4 Nov 2009 19:24:22 +0000 (+0200) Subject: dump: Revise whitespace usage X-Git-Tag: v1.2~26 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=jansson.git;a=commitdiff_plain;h=f236c14dc5457a41119492ebce41b8920fd31f65 dump: Revise whitespace usage - Never append newline to output - By default, add spaces between array and object items for more readable output - Introduce the flag JSON_COMPACT to not add the aforementioned spaces --- diff --git a/doc/apiref.rst b/doc/apiref.rst index 3ba5fbf..cf8842d 100644 --- a/doc/apiref.rst +++ b/doc/apiref.rst @@ -494,16 +494,30 @@ 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. +By default, the output has no newlines, and spaces are used between +array and object elements for a readable output. This behavior can be +altered by using the ``JSON_INDENT`` and ``JSON_COMPACT`` flags +described below. A newline is never appended to the end of the encoded +JSON data. + Each function takes a *flags* parameter that controls some aspects of how the data is encoded. Its default value is 0. The following macros can be ORed together to obtain *flags*. ``JSON_INDENT(n)`` - Pretty-print the result, indenting arrays and objects by *n* - spaces. The valid range for *n* is between 0 and 255, other values - result in an undefined output. If ``JSON_INDENT`` is not used or - *n* is 0, no pretty-printing is done and the result is a compact - representation. + Pretty-print the result, using newlines between array and object + items, and indenting with *n* spaces. The valid range for *n* is + between 0 and 255, other values result in an undefined output. If + ``JSON_INDENT`` is not used or *n* is 0, no newlines are inserted + between array and object items. + +``JSON_COMPACT`` + This flag enables a compact representation, i.e. sets the separator + between array and object items to ``","`` and between object keys + and values to ``":"``. Without this flag, the corresponding + separators are ``", "`` and ``": "`` for more readable output. + + .. versionadded:: 1.2 The following functions perform the actual JSON encoding. The result is in UTF-8. diff --git a/src/dump.c b/src/dump.c index 7dbc9f2..ac0b8dc 100644 --- a/src/dump.c +++ b/src/dump.c @@ -42,7 +42,7 @@ static int dump_to_file(const char *buffer, int size, void *data) /* 256 spaces (the maximum indentation size) */ static char whitespace[] = " "; -static int dump_indent(unsigned long flags, int depth, dump_func dump, void *data) +static int dump_indent(unsigned long flags, int depth, int space, dump_func dump, void *data) { if(JSON_INDENT(flags) > 0) { @@ -57,6 +57,10 @@ static int dump_indent(unsigned long flags, int depth, dump_func dump, void *dat return -1; } } + else if(space && !(flags & JSON_COMPACT)) + { + return dump(" ", 1, data); + } return 0; } @@ -173,7 +177,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, return -1; if(n == 0) return dump("]", 1, data); - if(dump_indent(flags, depth + 1, dump, data)) + if(dump_indent(flags, depth + 1, 0, dump, data)) return -1; for(i = 0; i < n; ++i) { @@ -184,12 +188,12 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, if(i < n - 1) { if(dump(",", 1, data) || - dump_indent(flags, depth + 1, dump, data)) + dump_indent(flags, depth + 1, 1, dump, data)) return -1; } else { - if(dump_indent(flags, depth, dump, data)) + if(dump_indent(flags, depth, 0, dump, data)) return -1; } } @@ -202,6 +206,17 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, { json_object_t *object; void *iter; + const char *separator; + int separator_length; + + if(flags & JSON_COMPACT) { + separator = ":"; + separator_length = 1; + } + else { + separator = ": "; + separator_length = 2; + } /* detect circular references */ object = json_to_object(json); @@ -215,7 +230,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, return -1; if(!iter) return dump("}", 1, data); - if(dump_indent(flags, depth + 1, dump, data)) + if(dump_indent(flags, depth + 1, 0, dump, data)) return -1; while(iter) @@ -223,7 +238,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, void *next = json_object_iter_next((json_t *)json, iter); dump_string(json_object_iter_key(iter), dump, data); - if(dump(": ", 2, data) || + if(dump(separator, separator_length, data) || do_dump(json_object_iter_value(iter), flags, depth + 1, dump, data)) return -1; @@ -231,12 +246,12 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, if(next) { if(dump(",", 1, data) || - dump_indent(flags, depth + 1, dump, data)) + dump_indent(flags, depth + 1, 1, dump, data)) return -1; } else { - if(dump_indent(flags, depth, dump, data)) + if(dump_indent(flags, depth, 0, dump, data)) return -1; } @@ -270,11 +285,6 @@ char *json_dumps(const json_t *json, unsigned long flags) return NULL; } - if(dump_to_strbuffer("\n", 1, (void *)&strbuff)) { - strbuffer_close(&strbuff); - return NULL; - } - result = strdup(strbuffer_value(&strbuff)); strbuffer_close(&strbuff); @@ -286,9 +296,7 @@ int json_dumpf(const json_t *json, FILE *output, unsigned long flags) if(!json_is_array(json) && !json_is_object(json)) return -1; - if(do_dump(json, flags, 0, dump_to_file, (void *)output)) - return -1; - return dump_to_file("\n", 1, (void *)output); + return do_dump(json, flags, 0, dump_to_file, (void *)output); } int json_dump_file(const json_t *json, const char *path, unsigned long flags) diff --git a/src/jansson.h b/src/jansson.h index 50073d2..a3a97e0 100644 --- a/src/jansson.h +++ b/src/jansson.h @@ -143,6 +143,7 @@ json_t *json_loadf(FILE *input, json_error_t *error); json_t *json_load_file(const char *path, json_error_t *error); #define JSON_INDENT(n) (n & 0xFF) +#define JSON_COMPACT 0x100 char *json_dumps(const json_t *json, unsigned long flags); int json_dumpf(const json_t *json, FILE *output, unsigned long flags); diff --git a/test/.gitignore b/test/.gitignore index 09dfb4d..6f12c1f 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -3,6 +3,7 @@ loads_dumps load_file_dump_file testlogs testprogs/test_array +testprogs/test_dump testprogs/test_number testprogs/test_object testprogs/test_simple diff --git a/test/testprogs/Makefile.am b/test/testprogs/Makefile.am index 400a998..792196a 100644 --- a/test/testprogs/Makefile.am +++ b/test/testprogs/Makefile.am @@ -1,6 +1,7 @@ -check_PROGRAMS = test_array test_simple test_number test_object +check_PROGRAMS = test_array test_dump test_simple test_number test_object test_array_SOURCES = test_array.c util.h +test_dump_SOURCES = test_dump.c util.h test_simple_SOURCES = test_simple.c util.h test_number_SOURCES = test_number.c util.h test_object_SOURCES = test_object.c util.h diff --git a/test/testprogs/test_dump.c b/test/testprogs/test_dump.c new file mode 100644 index 0000000..2532fca --- /dev/null +++ b/test/testprogs/test_dump.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2009 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include +#include "util.h" + +static json_t *create_object() +{ + json_t *object; + + object = json_object(); + if(!object) + fail("unable to create an object"); + + if(json_object_set_new(object, "a", json_integer(1)) || + json_object_set_new(object, "b", json_integer(2))) + fail("unable to set object values"); + + return object; +} + +static json_t *create_array() +{ + json_t *array; + + array = json_array(); + if(!array) + fail("unable to create an array"); + + if(json_array_append_new(array, json_integer(1)) || + json_array_append_new(array, json_integer(2))) + fail("unable to append array values"); + + return array; +} + + +#define NORMAL_OBJECT "{\"a\": 1, \"b\": 2}" +#define NORMAL_ARRAY "[1, 2]" + +static void test_normal() +{ + json_t *object; + json_t *array; + char *result; + + object = create_object(); + array = create_array(); + + result = json_dumps(object, 0); + if(strcmp(result, NORMAL_OBJECT) != 0) + fail("unexpected encoded object"); + free(result); + + result = json_dumps(array, 0); + if(strcmp(result, NORMAL_ARRAY) != 0) + fail("unexpected encoded array"); + free(result); + + json_decref(object); + json_decref(array); +} + + +#define INDENTED_OBJECT \ + "{\n" \ + " \"a\": 1,\n" \ + " \"b\": 2\n" \ + "}" +#define INDENTED_ARRAY \ + "[\n" \ + " 1,\n" \ + " 2\n" \ + "]" + +static void test_indent() +{ + json_t *object; + json_t *array; + char *result; + + object = create_object(); + array = create_array(); + + result = json_dumps(object, JSON_INDENT(4)); + if(strcmp(result, INDENTED_OBJECT) != 0) + fail("unexpected encoded object"); + free(result); + + result = json_dumps(array, JSON_INDENT(4)); + if(strcmp(result, INDENTED_ARRAY) != 0) + fail("unexpected encoded array"); + free(result); + + json_decref(object); + json_decref(array); +} + + +#define COMPACT_OBJECT "{\"a\":1,\"b\":2}" +#define COMPACT_ARRAY "[1,2]" + +static void test_compact() +{ + json_t *object; + json_t *array; + char *result; + + object = create_object(); + array = create_array(); + + result = json_dumps(object, JSON_COMPACT); + if(strcmp(result, COMPACT_OBJECT) != 0) + fail("unexpected encoded object"); + free(result); + + result = json_dumps(array, JSON_COMPACT); + if(strcmp(result, COMPACT_ARRAY) != 0) + fail("unexpected encoded array"); + free(result); + + json_decref(object); + json_decref(array); +} + + +#define INDENTED_COMPACT_OBJECT \ + "{\n" \ + " \"a\":1,\n" \ + " \"b\":2\n" \ + "}" +#define INDENTED_COMPACT_ARRAY \ + "[\n" \ + " 1,\n" \ + " 2\n" \ + "]" + +static void test_compact_indent() +{ + json_t *object; + json_t *array; + char *result; + + object = create_object(); + array = create_array(); + + result = json_dumps(object, JSON_INDENT(4) | JSON_COMPACT); + if(strcmp(result, INDENTED_COMPACT_OBJECT) != 0) + fail("unexpected encoded object"); + free(result); + + result = json_dumps(array, JSON_INDENT(4) | JSON_COMPACT); + if(strcmp(result, INDENTED_COMPACT_ARRAY) != 0) + fail("unexpected encoded array"); + free(result); + + json_decref(object); + json_decref(array); +} + +int main(void) +{ + test_normal(); + test_indent(); + test_compact(); + test_compact_indent(); + + return 0; +}