diff options
| author | Jonathan Marler <johnnymarler@gmail.com> | 2022-06-30 15:02:09 -0600 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-07-24 11:51:59 +0300 |
| commit | f598234ee820ca0d57946542a852f193b21d847f (patch) | |
| tree | 5ab1dda8719c06cd4b52e2b7ce7c8f0c4b8f417a /lib/std/json.zig | |
| parent | a2ab9e36faded9755ecc1fe809c49140120c3c61 (diff) | |
| download | zig-f598234ee820ca0d57946542a852f193b21d847f.tar.gz zig-f598234ee820ca0d57946542a852f193b21d847f.zip | |
std.json: expose encodeJsonString and encodeJsonStringChars
Expose 2 functions from std.json. These functions take a slice of bytes
and forward them to a given writer as a JSON encoded string.
The use case I have for this is in a custom JsonStringWriter. This writer
takes data and automatically encodes it as JSON string characters and
forwards it to an underlying writer. I use this JsonStringWriter in
combination with std.fmt.format to go directly from a format string/arg
pair to JSON. This way I don't have to format my string into a separate
buffer first and encode it afterwards, which avoids the need to create
a temporary buffer to hold the unencoded but formatted string.
Diffstat (limited to 'lib/std/json.zig')
| -rw-r--r-- | lib/std/json.zig | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/lib/std/json.zig b/lib/std/json.zig index baf93af47c..548a3db94e 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -2163,45 +2163,51 @@ fn outputUnicodeEscape( } } -fn outputJsonString(value: []const u8, options: StringifyOptions, out_stream: anytype) !void { - try out_stream.writeByte('\"'); +/// Write `string` to `writer` as a JSON encoded string. +pub fn encodeJsonString(string: []const u8, options: StringifyOptions, writer: anytype) !void { + try writer.writeByte('\"'); + try encodeJsonStringChars(string, options, writer); + try writer.writeByte('\"'); +} + +/// Write `chars` to `writer` as JSON encoded string characters. +pub fn encodeJsonStringChars(chars: []const u8, options: StringifyOptions, writer: anytype) !void { var i: usize = 0; - while (i < value.len) : (i += 1) { - switch (value[i]) { + while (i < chars.len) : (i += 1) { + switch (chars[i]) { // normal ascii character - 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => |c| try out_stream.writeByte(c), + 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => |c| try writer.writeByte(c), // only 2 characters that *must* be escaped - '\\' => try out_stream.writeAll("\\\\"), - '\"' => try out_stream.writeAll("\\\""), + '\\' => try writer.writeAll("\\\\"), + '\"' => try writer.writeAll("\\\""), // solidus is optional to escape '/' => { if (options.string.String.escape_solidus) { - try out_stream.writeAll("\\/"); + try writer.writeAll("\\/"); } else { - try out_stream.writeByte('/'); + try writer.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"), + 0x8 => try writer.writeAll("\\b"), + 0xC => try writer.writeAll("\\f"), + '\n' => try writer.writeAll("\\n"), + '\r' => try writer.writeAll("\\r"), + '\t' => try writer.writeAll("\\t"), else => { - const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable; + const ulen = std.unicode.utf8ByteSequenceLength(chars[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); + const codepoint = std.unicode.utf8Decode(chars[i .. i + ulen]) catch unreachable; + try outputUnicodeEscape(codepoint, writer); } else { - try out_stream.writeAll(value[i .. i + ulen]); + try writer.writeAll(chars[i .. i + ulen]); } i += ulen - 1; }, } } - try out_stream.writeByte('\"'); } pub fn stringify( @@ -2288,7 +2294,7 @@ pub fn stringify( if (child_options.whitespace) |child_whitespace| { try child_whitespace.outputIndent(out_stream); } - try outputJsonString(Field.name, options, out_stream); + try encodeJsonString(Field.name, options, out_stream); try out_stream.writeByte(':'); if (child_options.whitespace) |child_whitespace| { if (child_whitespace.separator) { @@ -2321,7 +2327,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 outputJsonString(value, options, out_stream); + try encodeJsonString(value, options, out_stream); return; } |
