commit c97db8e4974b912c7ae97df878d04d2d71480b9a (tree)
parent 5f3d9e0b7a67b8a23b659ca7dada8641f55b8503
Author: pfg <pfg@pfg.pw>
Date: Sat, 7 Sep 2024 11:06:41 -0400
Support stringifying non-exhaustive enum to json (#21228)
Diffstat:
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/lib/std/json/stringify.zig b/lib/std/json/stringify.zig
@@ -483,6 +483,7 @@ pub fn WriteStream(
/// * 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`.
/// * Zig `enum` -> JSON string naming the active tag.
/// * 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`.
+ /// * If the enum is non-exhaustive, unnamed values are rendered as integers.
/// * Zig untyped enum literal -> JSON string naming the active tag.
/// * Zig error -> JSON string naming the error.
/// * Zig `*T` -> the rendering of `T`. Note there is no guard against circular-reference infinite recursion.
@@ -540,11 +541,24 @@ pub fn WriteStream(
return try self.write(null);
}
},
- .@"enum", .enum_literal => {
+ .@"enum" => |enum_info| {
if (std.meta.hasFn(T, "jsonStringify")) {
return value.jsonStringify(self);
}
+ if (!enum_info.is_exhaustive) {
+ inline for (enum_info.fields) |field| {
+ if (value == @field(T, field.name)) {
+ break;
+ }
+ } else {
+ return self.write(@intFromEnum(value));
+ }
+ }
+
+ return self.stringValue(@tagName(value));
+ },
+ .enum_literal => {
return self.stringValue(@tagName(value));
},
.@"union" => {
diff --git a/lib/std/json/stringify_test.zig b/lib/std/json/stringify_test.zig
@@ -172,6 +172,15 @@ test "stringify enums" {
try testStringify("\"bar\"", E.bar, .{});
}
+test "stringify non-exhaustive enum" {
+ const E = enum(u8) {
+ foo = 0,
+ _,
+ };
+ try testStringify("\"foo\"", E.foo, .{});
+ try testStringify("1", @as(E, @enumFromInt(1)), .{});
+}
+
test "stringify enum literals" {
try testStringify("\"foo\"", .foo, .{});
try testStringify("\"bar\"", .bar, .{});