From 9dec65ca6cd4c6699c58fad0457d9a21b93ead26 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 21 Apr 2026 05:23:13 +0300 Subject: [PATCH] x.json2: fix @[json_as_number] enum attribute silently ignored on encode (fixes #26906) --- vlib/x/json2/README.md | 3 +++ vlib/x/json2/attr_utils.v | 10 ++++++++++ vlib/x/json2/encode.v | 4 ++-- vlib/x/json2/tests/encode_test.v | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/vlib/x/json2/README.md b/vlib/x/json2/README.md index 4a3f17f09..7ec32b443 100644 --- a/vlib/x/json2/README.md +++ b/vlib/x/json2/README.md @@ -29,6 +29,9 @@ fn main() { } ``` +Enums encode as strings by default. Use `@[json_as_number]` on an enum to emit +its integer value instead. + #### decode[T] ```v diff --git a/vlib/x/json2/attr_utils.v b/vlib/x/json2/attr_utils.v index b3b853694..0ac790496 100644 --- a/vlib/x/json2/attr_utils.v +++ b/vlib/x/json2/attr_utils.v @@ -41,3 +41,13 @@ fn json_attr_value_range(attr string) ?(int, int) { } return start, end } + +@[inline] +fn enum_uses_json_as_number[T]() bool { + $for attr in T.attributes { + if attr.name == 'json_as_number' { + return true + } + } + return false +} diff --git a/vlib/x/json2/encode.v b/vlib/x/json2/encode.v index b0159b95b..838909d0e 100644 --- a/vlib/x/json2/encode.v +++ b/vlib/x/json2/encode.v @@ -112,7 +112,7 @@ fn (mut encoder Encoder) encode_value[T](val T) { } encoder.output << `}` } $else $if T.unaliased_typ is $enum { - if encoder.enum_as_int { + if encoder.enum_as_int || enum_uses_json_as_number[T]() { encoder.encode_number(int(val)) } else { mut enum_val := 'unknown enum value' @@ -408,7 +408,7 @@ fn (mut encoder Encoder) encode_map[K, T](val map[K]T) { } fn (mut encoder Encoder) encode_enum[T](val T) { - if encoder.enum_as_int { + if encoder.enum_as_int || enum_uses_json_as_number[T]() { encoder.encode_number(int(val)) } else { mut enum_val := 'unknown enum value' diff --git a/vlib/x/json2/tests/encode_test.v b/vlib/x/json2/tests/encode_test.v index 856155854..04c1c73f1 100644 --- a/vlib/x/json2/tests/encode_test.v +++ b/vlib/x/json2/tests/encode_test.v @@ -16,6 +16,12 @@ enum TestEnum { type EnumAlias = TestEnum +@[json_as_number] +enum NumberedTestEnum { + a + b = 5 +} + type Sum = int | string type SumAlias = Sum @@ -25,6 +31,10 @@ struct Basic { c bool } +struct NumberedEnumWrap { + a NumberedTestEnum +} + type BasicAlias = Basic struct Opt { @@ -142,6 +152,14 @@ fn test_enums() { assert json.encode(EnumAlias(TestEnum.d)) == '"d"' } +fn test_enum_json_as_number_attribute() { + assert json.encode(NumberedTestEnum.a) == '0' + assert json.encode(NumberedTestEnum.b) == '5' + assert json.encode(NumberedEnumWrap{ + a: .a + }) == '{"a":0}' +} + fn test_sumtypes() { assert json.encode(Sum(10)) == '10' assert json.encode(Sum('hi')) == '"hi"' -- 2.39.5