authorgravatar for andreas.reischuck@hicknhack-software.comAndreas Reischuck <andreas.reischuck@hicknhack-software.com> 2022-05-10 00:06:00+02:00
committergravatar for andreas.reischuck@hicknhack-software.comAndreas Reischuck <andreas.reischuck@hicknhack-software.com> 2022-05-10 09:56:49+02:00
log10a671ad091bbb9453bc07e67086f68b07bff928
tree045a51950370f494d87c819cbec442725fce7fac
parentb57a356bb638be402ccc169c1076c53792d2ebe4

std.json stringify fix object keys are always is strings

* extracted outputJsonString to avoid code duplication

1 files changed, 43 insertions(+), 39 deletions(-)

lib/std/json.zig+43-39
...@@ -2963,6 +2963,47 @@ fn outputUnicodeEscape(...@@ -2963,6 +2963,47 @@ fn outputUnicodeEscape(
2963 }2963 }
2964}2964}
29652965
2966fn outputJsonString(value: []const u8, options: StringifyOptions, out_stream: anytype) !void {
2967 try out_stream.writeByte('\"');
2968 var i: usize = 0;
2969 while (i < value.len) : (i += 1) {
2970 switch (value[i]) {
2971 // normal ascii character
2972 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => |c| try out_stream.writeByte(c),
2973 // only 2 characters that *must* be escaped
2974 '\\' => try out_stream.writeAll("\\\\"),
2975 '\"' => try out_stream.writeAll("\\\""),
2976 // solidus is optional to escape
2977 '/' => {
2978 if (options.string.String.escape_solidus) {
2979 try out_stream.writeAll("\\/");
2980 } else {
2981 try out_stream.writeByte('/');
2982 }
2983 },
2984 // control characters with short escapes
2985 // TODO: option to switch between unicode and 'short' forms?
2986 0x8 => try out_stream.writeAll("\\b"),
2987 0xC => try out_stream.writeAll("\\f"),
2988 '\n' => try out_stream.writeAll("\\n"),
2989 '\r' => try out_stream.writeAll("\\r"),
2990 '\t' => try out_stream.writeAll("\\t"),
2991 else => {
2992 const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
2993 // control characters (only things left with 1 byte length) should always be printed as unicode escapes
2994 if (ulen == 1 or options.string.String.escape_unicode) {
2995 const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
2996 try outputUnicodeEscape(codepoint, out_stream);
2997 } else {
2998 try out_stream.writeAll(value[i .. i + ulen]);
2999 }
3000 i += ulen - 1;
3001 },
3002 }
3003 }
3004 try out_stream.writeByte('\"');
3005}
3006
2966pub fn stringify(3007pub fn stringify(
2967 value: anytype,3008 value: anytype,
2968 options: StringifyOptions,3009 options: StringifyOptions,
...@@ -3048,7 +3089,7 @@ pub fn stringify(...@@ -3048,7 +3089,7 @@ pub fn stringify(
3048 try out_stream.writeByte('\n');3089 try out_stream.writeByte('\n');
3049 try child_whitespace.outputIndent(out_stream);3090 try child_whitespace.outputIndent(out_stream);
3050 }3091 }
3051 try stringify(Field.name, options, out_stream);3092 try outputJsonString(Field.name, options, out_stream);
3052 try out_stream.writeByte(':');3093 try out_stream.writeByte(':');
3053 if (child_options.whitespace) |child_whitespace| {3094 if (child_options.whitespace) |child_whitespace| {
3054 if (child_whitespace.separator) {3095 if (child_whitespace.separator) {
...@@ -3082,44 +3123,7 @@ pub fn stringify(...@@ -3082,44 +3123,7 @@ pub fn stringify(
3082 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)3123 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
3083 .Slice => {3124 .Slice => {
3084 if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) {3125 if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) {
3085 try out_stream.writeByte('\"');3126 try outputJsonString(value, options, out_stream);
3086 var i: usize = 0;
3087 while (i < value.len) : (i += 1) {
3088 switch (value[i]) {
3089 // normal ascii character
3090 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => |c| try out_stream.writeByte(c),
3091 // only 2 characters that *must* be escaped
3092 '\\' => try out_stream.writeAll("\\\\"),
3093 '\"' => try out_stream.writeAll("\\\""),
3094 // solidus is optional to escape
3095 '/' => {
3096 if (options.string.String.escape_solidus) {
3097 try out_stream.writeAll("\\/");
3098 } else {
3099 try out_stream.writeByte('/');
3100 }
3101 },
3102 // control characters with short escapes
3103 // TODO: option to switch between unicode and 'short' forms?
3104 0x8 => try out_stream.writeAll("\\b"),
3105 0xC => try out_stream.writeAll("\\f"),
3106 '\n' => try out_stream.writeAll("\\n"),
3107 '\r' => try out_stream.writeAll("\\r"),
3108 '\t' => try out_stream.writeAll("\\t"),
3109 else => {
3110 const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
3111 // control characters (only things left with 1 byte length) should always be printed as unicode escapes
3112 if (ulen == 1 or options.string.String.escape_unicode) {
3113 const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
3114 try outputUnicodeEscape(codepoint, out_stream);
3115 } else {
3116 try out_stream.writeAll(value[i .. i + ulen]);
3117 }
3118 i += ulen - 1;
3119 },
3120 }
3121 }
3122 try out_stream.writeByte('\"');
3123 return;3127 return;
3124 }3128 }
31253129