aboutsummaryrefslogtreecommitdiff
path: root/lib/std/json.zig
diff options
context:
space:
mode:
authorChris Heyes <rumcode@icloud.com>2021-11-15 23:56:51 +0000
committerGitHub <noreply@github.com>2021-11-15 18:56:51 -0500
commit5d2a77cd9ac44df4c0e8b5affd983cae6d00ce55 (patch)
tree4026836f2a22a91fec29599db41ed98e24d47d0e /lib/std/json.zig
parent39c0d8bd2c2bd048da6ea1821c6c46aa60fa2907 (diff)
downloadzig-5d2a77cd9ac44df4c0e8b5affd983cae6d00ce55.tar.gz
zig-5d2a77cd9ac44df4c0e8b5affd983cae6d00ce55.zip
Json Stringify option to not write out null optional fields (#8979)
Diffstat (limited to 'lib/std/json.zig')
-rw-r--r--lib/std/json.zig76
1 files changed, 61 insertions, 15 deletions
diff --git a/lib/std/json.zig b/lib/std/json.zig
index d1d88ebe91..9c9af6e215 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -2846,6 +2846,9 @@ pub const StringifyOptions = struct {
/// Controls the whitespace emitted
whitespace: ?Whitespace = null,
+ /// Should optional fields with null value be written?
+ emit_null_optional_fields: bool = true,
+
string: StringOptions = StringOptions{ .String = .{} },
/// Should []u8 be serialised as a string? or an array?
@@ -2942,7 +2945,7 @@ pub fn stringify(
}
try out_stream.writeByte('{');
- comptime var field_output = false;
+ var field_output = false;
var child_options = options;
if (child_options.whitespace) |*child_whitespace| {
child_whitespace.indent_level += 1;
@@ -2951,23 +2954,36 @@ pub fn stringify(
// don't include void fields
if (Field.field_type == void) continue;
- if (!field_output) {
- field_output = true;
- } else {
- try out_stream.writeByte(',');
- }
- if (child_options.whitespace) |child_whitespace| {
- try out_stream.writeByte('\n');
- try child_whitespace.outputIndent(out_stream);
+ var emit_field = true;
+
+ // don't include optional fields that are null when emit_null_optional_fields is set to false
+ if (@typeInfo(Field.field_type) == .Optional) {
+ if (options.emit_null_optional_fields == false) {
+ if (@field(value, Field.name) == null) {
+ emit_field = false;
+ }
+ }
}
- try stringify(Field.name, options, out_stream);
- try out_stream.writeByte(':');
- if (child_options.whitespace) |child_whitespace| {
- if (child_whitespace.separator) {
- try out_stream.writeByte(' ');
+
+ if (emit_field) {
+ if (!field_output) {
+ field_output = true;
+ } else {
+ try out_stream.writeByte(',');
+ }
+ if (child_options.whitespace) |child_whitespace| {
+ try out_stream.writeByte('\n');
+ try child_whitespace.outputIndent(out_stream);
}
+ try stringify(Field.name, options, out_stream);
+ try out_stream.writeByte(':');
+ if (child_options.whitespace) |child_whitespace| {
+ if (child_whitespace.separator) {
+ try out_stream.writeByte(' ');
+ }
+ }
+ try stringify(@field(value, Field.name), child_options, out_stream);
}
- try stringify(@field(value, Field.name), child_options, out_stream);
}
if (field_output) {
if (options.whitespace) |whitespace| {
@@ -3257,3 +3273,33 @@ test "stringify struct with custom stringifier" {
test "stringify vector" {
try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{});
}
+
+test "stringify null optional fields" {
+ const MyStruct = struct {
+ optional: ?[]const u8 = null,
+ required: []const u8 = "something",
+ another_optional: ?[]const u8 = null,
+ another_required: []const u8 = "something else",
+ };
+ try teststringify(
+ \\{"optional":null,"required":"something","another_optional":null,"another_required":"something else"}
+ ,
+ MyStruct{},
+ StringifyOptions{},
+ );
+ try teststringify(
+ \\{"required":"something","another_required":"something else"}
+ ,
+ MyStruct{},
+ StringifyOptions{ .emit_null_optional_fields = false },
+ );
+
+ try std.testing.expect(try parsesTo(
+ MyStruct,
+ MyStruct{},
+ &TokenStream.init(
+ \\{"required":"something","another_required":"something else"}
+ ),
+ .{ .allocator = std.testing.allocator },
+ ));
+}