aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPetri Lehtinen <petri@digip.org>2009-12-07 13:16:45 +0200
committerPetri Lehtinen <petri@digip.org>2009-12-16 23:12:39 +0200
commit19a606d7361e73ff2f5e0b240c2adb07b35e4273 (patch)
tree19e727b646e5233b46c78a982bd1b6d633b92713 /src
parent3add1cf36183d4acefa11ae1c0acd6d92719ac02 (diff)
downloadjansson-19a606d7361e73ff2f5e0b240c2adb07b35e4273.zip
jansson-19a606d7361e73ff2f5e0b240c2adb07b35e4273.tar.gz
jansson-19a606d7361e73ff2f5e0b240c2adb07b35e4273.tar.bz2
Implement JSON_SORT_KEYS encoding flag
With this flag, the objects are sorted by key when encoding.
Diffstat (limited to 'src')
-rw-r--r--src/dump.c99
-rw-r--r--src/jansson.h1
2 files changed, 87 insertions, 13 deletions
diff --git a/src/dump.c b/src/dump.c
index dc3fcbc..328e93b 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -10,6 +10,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
+#include <assert.h>
#include <jansson.h>
#include "jansson_private.h"
@@ -153,6 +154,11 @@ static int dump_string(const char *str, int ascii, dump_func dump, void *data)
return dump("\"", 1, data);
}
+static int object_key_cmp(const void *key1, const void *key2)
+{
+ return strcmp(*(const char **)key1, *(const char **)key2);
+}
+
static int do_dump(const json_t *json, unsigned long flags, int depth,
dump_func dump, void *data)
{
@@ -269,29 +275,96 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
if(dump_indent(flags, depth + 1, 0, dump, data))
return -1;
- while(iter)
+ if(flags & JSON_SORT_KEYS)
{
- void *next = json_object_iter_next((json_t *)json, iter);
+ /* Sort keys */
- dump_string(json_object_iter_key(iter), ascii, dump, data);
- if(dump(separator, separator_length, data) ||
- do_dump(json_object_iter_value(iter), flags, depth + 1,
- dump, data))
+ const char **keys;
+ unsigned int size;
+ unsigned int i;
+
+ size = json_object_size(json);
+ keys = malloc(size * sizeof(const char *));
+ if(!keys)
return -1;
- if(next)
+ i = 0;
+ while(iter)
{
- if(dump(",", 1, data) ||
- dump_indent(flags, depth + 1, 1, dump, data))
- return -1;
+ keys[i] = json_object_iter_key(iter);
+ iter = json_object_iter_next((json_t *)json, iter);
+ i++;
}
- else
+ assert(i == size);
+
+ qsort(keys, size, sizeof(const char *), object_key_cmp);
+
+ for(i = 0; i < size; i++)
{
- if(dump_indent(flags, depth, 0, dump, data))
+ const char *key;
+ json_t *value;
+
+ key = keys[i];
+ value = json_object_get(json, key);
+ assert(value);
+
+ dump_string(key, ascii, dump, data);
+ if(dump(separator, separator_length, data) ||
+ do_dump(value, flags, depth + 1, dump, data))
+ {
+ free(keys);
return -1;
+ }
+
+ if(i < size - 1)
+ {
+ if(dump(",", 1, data) ||
+ dump_indent(flags, depth + 1, 1, dump, data))
+ {
+ free(keys);
+ return -1;
+ }
+ }
+ else
+ {
+ if(dump_indent(flags, depth, 0, dump, data))
+ {
+ free(keys);
+ return -1;
+ }
+ }
}
- iter = next;
+ free(keys);
+ }
+ else
+ {
+ /* Don't sort keys */
+
+ while(iter)
+ {
+ void *next = json_object_iter_next((json_t *)json, iter);
+
+ dump_string(json_object_iter_key(iter), ascii, dump, 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, 1, dump, data))
+ return -1;
+ }
+ else
+ {
+ if(dump_indent(flags, depth, 0, dump, data))
+ return -1;
+ }
+
+ iter = next;
+ }
}
object->visited = 0;
diff --git a/src/jansson.h b/src/jansson.h
index d59fe10..607dfb5 100644
--- a/src/jansson.h
+++ b/src/jansson.h
@@ -144,6 +144,7 @@ json_t *json_load_file(const char *path, json_error_t *error);
#define JSON_INDENT(n) (n & 0xFF)
#define JSON_COMPACT 0x100
#define JSON_ENSURE_ASCII 0x200
+#define JSON_SORT_KEYS 0x400
char *json_dumps(const json_t *json, unsigned long flags);
int json_dumpf(const json_t *json, FILE *output, unsigned long flags);