authorgravatar for pfg@pfg.pwpfg <pfg@pfg.pw> 2024-09-07 11:06:41-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-09-07 11:06:41-04:00
logc97db8e4974b912c7ae97df878d04d2d71480b9a
tree8457530d58fb793733dff8ac83cb4de8395f12d3
parent5f3d9e0b7a67b8a23b659ca7dada8641f55b8503
signaturebadge-check Signed by PGP key B5690EEEBB952194

Support stringifying non-exhaustive enum to json (#21228)


2 files changed, 24 insertions(+), 1 deletions(-)

lib/std/json/stringify.zig+15-1
...@@ -483,6 +483,7 @@ pub fn WriteStream(...@@ -483,6 +483,7 @@ pub fn WriteStream(
483 /// * 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`.483 /// * 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`.
484 /// * Zig `enum` -> JSON string naming the active tag.484 /// * Zig `enum` -> JSON string naming the active tag.
485 /// * 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`.485 /// * 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.
486 /// * Zig untyped enum literal -> JSON string naming the active tag.487 /// * Zig untyped enum literal -> JSON string naming the active tag.
487 /// * Zig error -> JSON string naming the error.488 /// * Zig error -> JSON string naming the error.
488 /// * Zig `*T` -> the rendering of `T`. Note there is no guard against circular-reference infinite recursion.489 /// * Zig `*T` -> the rendering of `T`. Note there is no guard against circular-reference infinite recursion.
...@@ -540,11 +541,24 @@ pub fn WriteStream(...@@ -540,11 +541,24 @@ pub fn WriteStream(
540 return try self.write(null);541 return try self.write(null);
541 }542 }
542 },543 },
543 .@"enum", .enum_literal => {544 .@"enum" => |enum_info| {
544 if (std.meta.hasFn(T, "jsonStringify")) {545 if (std.meta.hasFn(T, "jsonStringify")) {
545 return value.jsonStringify(self);546 return value.jsonStringify(self);
546 }547 }
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 => {
548 return self.stringValue(@tagName(value));562 return self.stringValue(@tagName(value));
549 },563 },
550 .@"union" => {564 .@"union" => {
lib/std/json/stringify_test.zig+9
...@@ -172,6 +172,15 @@ test "stringify enums" {...@@ -172,6 +172,15 @@ test "stringify enums" {
172 try testStringify("\"bar\"", E.bar, .{});172 try testStringify("\"bar\"", E.bar, .{});
173}173}
174174
175test "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
175test "stringify enum literals" {184test "stringify enum literals" {
176 try testStringify("\"foo\"", .foo, .{});185 try testStringify("\"foo\"", .foo, .{});
177 try testStringify("\"bar\"", .bar, .{});186 try testStringify("\"bar\"", .bar, .{});