diff options
author | Petri Lehtinen <petri@digip.org> | 2009-12-07 13:16:45 +0200 |
---|---|---|
committer | Petri Lehtinen <petri@digip.org> | 2009-12-16 23:12:39 +0200 |
commit | 19a606d7361e73ff2f5e0b240c2adb07b35e4273 (patch) | |
tree | 19e727b646e5233b46c78a982bd1b6d633b92713 /src | |
parent | 3add1cf36183d4acefa11ae1c0acd6d92719ac02 (diff) | |
download | jansson-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.c | 99 | ||||
-rw-r--r-- | src/jansson.h | 1 |
2 files changed, 87 insertions, 13 deletions
@@ -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); |