diff --git a/src/dump.c b/src/dump.c index 4251104..30d5433 100644 --- a/src/dump.c +++ b/src/dump.c @@ -62,7 +62,7 @@ static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t return 0; } -static int dump_string(const char *str, int ascii, json_dump_callback_t dump, void *data) +static int dump_string(const char *str, int ascii, json_dump_callback_t dump, void *data, size_t flags) { const char *pos, *end; int32_t codepoint; @@ -84,7 +84,7 @@ static int dump_string(const char *str, int ascii, json_dump_callback_t dump, vo return -1; /* mandatory escape or control char */ - if(codepoint == '\\' || codepoint == '"' || codepoint < 0x20) + if(codepoint == '\\' || codepoint == '/' || codepoint == '"' || codepoint < 0x20) break; /* non-ASCII */ @@ -102,7 +102,7 @@ static int dump_string(const char *str, int ascii, json_dump_callback_t dump, vo if(end == pos) break; - /* handle \, ", and control codes */ + /* handle \, /, ", and control codes */ length = 2; switch(codepoint) { @@ -113,6 +113,14 @@ static int dump_string(const char *str, int ascii, json_dump_callback_t dump, vo case '\n': text = "\\n"; break; case '\r': text = "\\r"; break; case '\t': text = "\\t"; break; + case '/': + if (flags & JSON_ESCAPE_SLASH) + text = "\\/"; + else { + text = "/"; + length = 1; + } + break; default: { /* codepoint is in BMP */ @@ -206,7 +214,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, } case JSON_STRING: - return dump_string(json_string_value(json), ascii, dump, data); + return dump_string(json_string_value(json), ascii, dump, data, flags); case JSON_ARRAY: { @@ -327,7 +335,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, value = json_object_get(json, key); assert(value); - dump_string(key, ascii, dump, data); + dump_string(key, ascii, dump, data, flags); if(dump(separator, separator_length, data) || do_dump(value, flags, depth + 1, dump, data)) { @@ -364,7 +372,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, { void *next = json_object_iter_next((json_t *)json, iter); - dump_string(json_object_iter_key(iter), ascii, dump, data); + dump_string(json_object_iter_key(iter), ascii, dump, data, flags); if(dump(separator, separator_length, data) || do_dump(json_object_iter_value(iter), flags, depth + 1, dump, data)) diff --git a/src/jansson.h b/src/jansson.h index e22b68f..966ceeb 100644 --- a/src/jansson.h +++ b/src/jansson.h @@ -249,6 +249,7 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla #define JSON_SORT_KEYS 0x80 #define JSON_PRESERVE_ORDER 0x100 #define JSON_ENCODE_ANY 0x200 +#define JSON_ESCAPE_SLASH 0x400 typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); diff --git a/test/suites/api/test_dump.c b/test/suites/api/test_dump.c index c1a3763..8cd659c 100644 --- a/test/suites/api/test_dump.c +++ b/test/suites/api/test_dump.c @@ -133,9 +133,34 @@ static void encode_other_than_array_or_object() } +static void escape_slashes() +{ + /* Test dump escaping slashes */ + + json_t *json; + char *result; + + json = json_object(); + json_object_set_new(json, "url", json_string("https://github.com/akheron/jansson")); + + result = json_dumps(json, 0); + if(!result || strcmp(result, "{\"url\": \"https://github.com/akheron/jansson\"}")) + fail("json_dumps failed to not escape slashes"); + + free(result); + + result = json_dumps(json, JSON_ESCAPE_SLASH); + if(!result || strcmp(result, "{\"url\": \"https:\\/\\/github.com\\/akheron\\/jansson\"}")) + fail("json_dumps failed to escape slashes"); + + free(result); + json_decref(json); +} + static void run_tests() { encode_twice(); circular_references(); encode_other_than_array_or_object(); + escape_slashes(); }