mirror of
https://github.com/akheron/jansson.git
synced 2025-04-06 05:55:05 +00:00
Implement JSON_SORT_KEYS encoding flag
With this flag, the objects are sorted by key when encoding.
This commit is contained in:
parent
3add1cf361
commit
19a606d736
8 changed files with 132 additions and 13 deletions
|
@ -526,6 +526,13 @@ can be ORed together to obtain *flags*.
|
|||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
``JSON_SORT_KEYS``
|
||||
If this flag is used, all the objects in output are sorted by key.
|
||||
This is useful e.g. if two JSON texts are diffed or visually
|
||||
compared.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
The following functions perform the actual JSON encoding. The result
|
||||
is in UTF-8.
|
||||
|
||||
|
|
99
src/dump.c
99
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -53,6 +53,9 @@ int main(int argc, char *argv[])
|
|||
if(getenv_int("JSON_ENSURE_ASCII"))
|
||||
flags |= JSON_ENSURE_ASCII;
|
||||
|
||||
if(getenv_int("JSON_SORT_KEYS"))
|
||||
flags |= JSON_SORT_KEYS;
|
||||
|
||||
json = json_loadf(stdin, &error);
|
||||
if(!json) {
|
||||
fprintf(stderr, "%d\n%s\n", error.line, error.text);
|
||||
|
|
32
test/suites/encoding-flags/run
Executable file
32
test/suites/encoding-flags/run
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 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.
|
||||
|
||||
is_test() {
|
||||
test -d $test_path
|
||||
}
|
||||
|
||||
run_test() {
|
||||
(
|
||||
if [ -f $test_path/env ]; then
|
||||
. $test_path/env
|
||||
fi
|
||||
$json_process <$test_path/input >$test_log/stdout 2>$test_log/stderr
|
||||
)
|
||||
valgrind_check $test_log/stderr || return 1
|
||||
cmp -s $test_path/output $test_log/stdout
|
||||
}
|
||||
|
||||
show_error() {
|
||||
valgrind_show_error && return
|
||||
|
||||
echo "EXPECTED OUTPUT:"
|
||||
nl -bn $test_path/output
|
||||
echo "ACTUAL OUTPUT:"
|
||||
nl -bn $test_log/stdout
|
||||
}
|
||||
|
||||
. $top_srcdir/test/scripts/run-tests.sh
|
1
test/suites/encoding-flags/sort-keys/env
Normal file
1
test/suites/encoding-flags/sort-keys/env
Normal file
|
@ -0,0 +1 @@
|
|||
export JSON_SORT_KEYS=1
|
1
test/suites/encoding-flags/sort-keys/input
Normal file
1
test/suites/encoding-flags/sort-keys/input
Normal file
|
@ -0,0 +1 @@
|
|||
{"foo": 1, "bar": 2, "baz": 3, "quux": 4}
|
1
test/suites/encoding-flags/sort-keys/output
Normal file
1
test/suites/encoding-flags/sort-keys/output
Normal file
|
@ -0,0 +1 @@
|
|||
{"bar": 2, "baz": 3, "foo": 1, "quux": 4}
|
Loading…
Add table
Reference in a new issue