diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-05-11 19:20:19 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-11 19:20:19 +0300 |
| commit | 090461a6959ccebbc0c79cacebcf52bc43d66b9e (patch) | |
| tree | a4c80e2a895de8aa1da67f4bfbefe15e8d21f654 /lib/std | |
| parent | 6608fa135321c2caa989a4e0357307874c644b6b (diff) | |
| parent | 10a671ad091bbb9453bc07e67086f68b07bff928 (diff) | |
| download | zig-090461a6959ccebbc0c79cacebcf52bc43d66b9e.tar.gz zig-090461a6959ccebbc0c79cacebcf52bc43d66b9e.zip | |
Merge pull request #11618 from arBmind/json-stringify-patch
JSON stringify string setting affects keys
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/json.zig | 87 |
1 files changed, 48 insertions, 39 deletions
diff --git a/lib/std/json.zig b/lib/std/json.zig index b670e488b2..2650b98822 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -2963,6 +2963,47 @@ fn outputUnicodeEscape( } } +fn outputJsonString(value: []const u8, options: StringifyOptions, out_stream: anytype) !void { + try out_stream.writeByte('\"'); + var i: usize = 0; + while (i < value.len) : (i += 1) { + switch (value[i]) { + // normal ascii character + 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => |c| try out_stream.writeByte(c), + // only 2 characters that *must* be escaped + '\\' => try out_stream.writeAll("\\\\"), + '\"' => try out_stream.writeAll("\\\""), + // solidus is optional to escape + '/' => { + if (options.string.String.escape_solidus) { + try out_stream.writeAll("\\/"); + } else { + try out_stream.writeByte('/'); + } + }, + // control characters with short escapes + // TODO: option to switch between unicode and 'short' forms? + 0x8 => try out_stream.writeAll("\\b"), + 0xC => try out_stream.writeAll("\\f"), + '\n' => try out_stream.writeAll("\\n"), + '\r' => try out_stream.writeAll("\\r"), + '\t' => try out_stream.writeAll("\\t"), + else => { + const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable; + // control characters (only things left with 1 byte length) should always be printed as unicode escapes + if (ulen == 1 or options.string.String.escape_unicode) { + const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable; + try outputUnicodeEscape(codepoint, out_stream); + } else { + try out_stream.writeAll(value[i .. i + ulen]); + } + i += ulen - 1; + }, + } + } + try out_stream.writeByte('\"'); +} + pub fn stringify( value: anytype, options: StringifyOptions, @@ -3048,7 +3089,7 @@ pub fn stringify( try out_stream.writeByte('\n'); try child_whitespace.outputIndent(out_stream); } - try stringify(Field.name, options, out_stream); + try outputJsonString(Field.name, options, out_stream); try out_stream.writeByte(':'); if (child_options.whitespace) |child_whitespace| { if (child_whitespace.separator) { @@ -3082,44 +3123,7 @@ pub fn stringify( // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) .Slice => { if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) { - try out_stream.writeByte('\"'); - var i: usize = 0; - while (i < value.len) : (i += 1) { - switch (value[i]) { - // normal ascii character - 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => |c| try out_stream.writeByte(c), - // only 2 characters that *must* be escaped - '\\' => try out_stream.writeAll("\\\\"), - '\"' => try out_stream.writeAll("\\\""), - // solidus is optional to escape - '/' => { - if (options.string.String.escape_solidus) { - try out_stream.writeAll("\\/"); - } else { - try out_stream.writeByte('/'); - } - }, - // control characters with short escapes - // TODO: option to switch between unicode and 'short' forms? - 0x8 => try out_stream.writeAll("\\b"), - 0xC => try out_stream.writeAll("\\f"), - '\n' => try out_stream.writeAll("\\n"), - '\r' => try out_stream.writeAll("\\r"), - '\t' => try out_stream.writeAll("\\t"), - else => { - const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable; - // control characters (only things left with 1 byte length) should always be printed as unicode escapes - if (ulen == 1 or options.string.String.escape_unicode) { - const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable; - try outputUnicodeEscape(codepoint, out_stream); - } else { - try out_stream.writeAll(value[i .. i + ulen]); - } - i += ulen - 1; - }, - } - } - try out_stream.writeByte('\"'); + try outputJsonString(value, options, out_stream); return; } @@ -3268,6 +3272,11 @@ test "stringify struct" { }{ .foo = 42 }, StringifyOptions{}); } +test "stringify struct with string as array" { + try teststringify("{\"foo\":\"bar\"}", .{ .foo = "bar" }, StringifyOptions{}); + try teststringify("{\"foo\":[98,97,114]}", .{ .foo = "bar" }, StringifyOptions{ .string = .Array }); +} + test "stringify struct with indentation" { try teststringify( \\{ |
