Skip to content

Commit c97db8e

Browse files
authored
Support stringifying non-exhaustive enum to json (ziglang#21228)
1 parent 5f3d9e0 commit c97db8e

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

lib/std/json/stringify.zig

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ pub fn WriteStream(
483483
/// * If the union declares a method `pub fn jsonStringify(self: *@This(), jw: anytype) !void`, it is called to do the serialization instead of the default behavior. The given `jw` is a pointer to this `WriteStream`.
484484
/// * Zig `enum` -> JSON string naming the active tag.
485485
/// * If the enum declares a method `pub fn jsonStringify(self: *@This(), jw: anytype) !void`, it is called to do the serialization instead of the default behavior. The given `jw` is a pointer to this `WriteStream`.
486+
/// * If the enum is non-exhaustive, unnamed values are rendered as integers.
486487
/// * Zig untyped enum literal -> JSON string naming the active tag.
487488
/// * Zig error -> JSON string naming the error.
488489
/// * Zig `*T` -> the rendering of `T`. Note there is no guard against circular-reference infinite recursion.
@@ -540,11 +541,24 @@ pub fn WriteStream(
540541
return try self.write(null);
541542
}
542543
},
543-
.@"enum", .enum_literal => {
544+
.@"enum" => |enum_info| {
544545
if (std.meta.hasFn(T, "jsonStringify")) {
545546
return value.jsonStringify(self);
546547
}
547548

549+
if (!enum_info.is_exhaustive) {
550+
inline for (enum_info.fields) |field| {
551+
if (value == @field(T, field.name)) {
552+
break;
553+
}
554+
} else {
555+
return self.write(@intFromEnum(value));
556+
}
557+
}
558+
559+
return self.stringValue(@tagName(value));
560+
},
561+
.enum_literal => {
548562
return self.stringValue(@tagName(value));
549563
},
550564
.@"union" => {

lib/std/json/stringify_test.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,15 @@ test "stringify enums" {
172172
try testStringify("\"bar\"", E.bar, .{});
173173
}
174174

175+
test "stringify non-exhaustive enum" {
176+
const E = enum(u8) {
177+
foo = 0,
178+
_,
179+
};
180+
try testStringify("\"foo\"", E.foo, .{});
181+
try testStringify("1", @as(E, @enumFromInt(1)), .{});
182+
}
183+
175184
test "stringify enum literals" {
176185
try testStringify("\"foo\"", .foo, .{});
177186
try testStringify("\"bar\"", .bar, .{});

0 commit comments

Comments
 (0)