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.
/* 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)
{
return -1;
}
}
+ else if(space && !(flags & JSON_COMPACT))
+ {
+ return dump(" ", 1, data);
+ }
return 0;
}
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) {
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;
}
}
{
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);
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)
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;
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;
}
return NULL;
}
- if(dump_to_strbuffer("\n", 1, (void *)&strbuff)) {
- strbuffer_close(&strbuff);
- return NULL;
- }
-
result = strdup(strbuffer_value(&strbuff));
strbuffer_close(&strbuff);
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)
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);
load_file_dump_file
testlogs
testprogs/test_array
+testprogs/test_dump
testprogs/test_number
testprogs/test_object
testprogs/test_simple
-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
--- /dev/null
+/*
+ * Copyright (c) 2009 Petri Lehtinen <petri@digip.org>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <jansson.h>
+#include <string.h>
+#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;
+}