summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--misc/json.c23
-rw-r--r--test/json.c3
2 files changed, 20 insertions, 6 deletions
diff --git a/misc/json.c b/misc/json.c
index 4797fde4d0..9cc0730e4d 100644
--- a/misc/json.c
+++ b/misc/json.c
@@ -24,7 +24,7 @@
*
* Does not support extensions like unquoted string literals.
*
- * Also see: http://tools.ietf.org/html/rfc4627
+ * Also see: http://tools.ietf.org/html/rfc8259
*
* JSON writer:
*
@@ -34,9 +34,6 @@
* to deal with somehow: either by using byte-strings for JSON, or by running
* a "fixup" pass on the input data. The latter could for example change
* invalid UTF-8 sequences to replacement characters.
- *
- * Currently, will insert \u literals for characters 0-31, '"', '\', and write
- * everything else literally.
*/
#include <stdlib.h>
@@ -218,6 +215,14 @@ int json_parse(void *ta_parent, struct mpv_node *dst, char **src, int max_depth)
#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
+static const char special_escape[] = {
+ ['\b'] = 'b',
+ ['\f'] = 'f',
+ ['\n'] = 'n',
+ ['\r'] = 'r',
+ ['\t'] = 't',
+};
+
static void write_json_str(bstr *b, unsigned char *str)
{
APPEND(b, "\"");
@@ -228,7 +233,15 @@ static void write_json_str(bstr *b, unsigned char *str)
if (!cur[0])
break;
bstr_xappend(NULL, b, (bstr){str, cur - str});
- bstr_xappend_asprintf(NULL, b, "\\u%04x", (unsigned char)cur[0]);
+ if (cur[0] == '\"') {
+ bstr_xappend(NULL, b, (bstr){"\\\"", 2});
+ } else if (cur[0] == '\\') {
+ bstr_xappend(NULL, b, (bstr){"\\\\", 2});
+ } else if (cur[0] < sizeof(special_escape) && special_escape[cur[0]]) {
+ bstr_xappend_asprintf(NULL, b, "\\%c", special_escape[cur[0]]);
+ } else {
+ bstr_xappend_asprintf(NULL, b, "\\u%04x", (unsigned char)cur[0]);
+ }
str = cur + 1;
}
APPEND(b, str);
diff --git a/test/json.c b/test/json.c
index 74fd20d748..d624f61cca 100644
--- a/test/json.c
+++ b/test/json.c
@@ -40,7 +40,8 @@ static const struct entry entries[] = {
{ "abc", .expect_fail = true},
{ " 123 ", "123", NODE_INT64(123)},
{ "123.25", "123.250000", NODE_FLOAT(123.25)},
- { TEXT("a\n\\"), TEXT("a\u000a\u005c"), NODE_STR("a\n\\")},
+ { TEXT("a\n\\\/\\\""), TEXT("a\n\\/\\\""), NODE_STR("a\n\\/\\\"")},
+ { TEXT("a\u2c29"), TEXT("aⰩ"), NODE_STR("a\342\260\251")},
{ "[1,2,3]", "[1,2,3]",
NODE_ARRAY(NODE_INT64(1), NODE_INT64(2), NODE_INT64(3))},
{ "[ ]", "[]", NODE_ARRAY()},