Commit 10a671ad09

Andreas Reischuck <andreas.reischuck@hicknhack-software.com>
2022-05-10 00:06:00
std.json stringify fix object keys are always is strings
* extracted outputJsonString to avoid code duplication
1 parent b57a356
Changed files (1)
lib
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;
                 }