Commit c97db8e497

pfg <pfg@pfg.pw>
2024-09-07 17:06:41
Support stringifying non-exhaustive enum to json (#21228)
1 parent 5f3d9e0
Changed files (2)
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" => {
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, .{});