From 6be2fbb700781cffff42cb8f82b451a0b30364fd Mon Sep 17 00:00:00 2001 From: gechandesu <47027335+gechandesu@users.noreply.github.com> Date: Mon, 26 Jan 2026 11:32:55 +0300 Subject: [PATCH] x.json2: add `@[json: name]` attr support for enum values (fix #26437) (#26441) --- vlib/x/json2/decode.v | 6 ++++++ vlib/x/json2/encode.v | 13 +++++++++++++ vlib/x/json2/tests/decode_enum_test.v | 24 +++++++++++++++++++++--- vlib/x/json2/tests/encode_test.v | 8 +++++++- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/vlib/x/json2/decode.v b/vlib/x/json2/decode.v index f9aafc2ad..17fbd0a3b 100644 --- a/vlib/x/json2/decode.v +++ b/vlib/x/json2/decode.v @@ -853,6 +853,12 @@ fn (mut decoder Decoder) decode_enum[T](mut val T) ! { decoder.decode_string(mut result)! $for value in T.values { + for attr in value.attrs { + if attr.starts_with('json: ') && attr[6..] == result { + val = value.value + return + } + } if value.name == result { val = value.value return diff --git a/vlib/x/json2/encode.v b/vlib/x/json2/encode.v index ff4f185d6..c79c3a004 100644 --- a/vlib/x/json2/encode.v +++ b/vlib/x/json2/encode.v @@ -299,6 +299,19 @@ fn (mut encoder Encoder) encode_enum[T](val T) { enum_val = enum_val[i + 1..enum_val.len - 1] } + mut attr_value := '' + $for member in T.values { + if member.value == val { + for attr in member.attrs { + if attr.starts_with('json: ') { + attr_value = attr[6..] + } + } + } + } + if attr_value != '' { + enum_val = attr_value + } encoder.output << `"` unsafe { encoder.output.push_many(enum_val.str, enum_val.len) } encoder.output << `"` diff --git a/vlib/x/json2/tests/decode_enum_test.v b/vlib/x/json2/tests/decode_enum_test.v index 21ed64974..bf39bc6f1 100644 --- a/vlib/x/json2/tests/decode_enum_test.v +++ b/vlib/x/json2/tests/decode_enum_test.v @@ -2,8 +2,9 @@ import x.json2 as json enum Bar { a - b + b @[json: 'BBB'] c = 10 + e @[badattr: 'bad'; foobar] } type BarAlias = Bar @@ -42,14 +43,31 @@ fn test_number_decode_fails() { fn test_string_decode() { assert json.decode[Bar]('"a"')! == Bar.a - assert json.decode[Bar]('"b"')! == Bar.b + assert json.decode[Bar]('"BBB"')! == Bar.b assert json.decode[Bar]('"c"')! == Bar.c assert json.decode[BarAlias]('"a"')! == Bar.a - assert json.decode[BarAlias]('"b"')! == Bar.b + assert json.decode[BarAlias]('"BBB"')! == Bar.b assert json.decode[BarAlias]('"c"')! == Bar.c } +fn test_string_decode_uses_only_json_attr() { + assert json.decode[Bar]('"e"')! == Bar.e + assert json.decode[BarAlias]('"e"')! == Bar.e + for badval in ['"badattr: bad"', '"bad"', '"foobar"'] { + if _ := json.decode[Bar](badval) { + assert false, '${badval} must not be decoded to Bar' + } else { + assert true + } + if _ := json.decode[BarAlias](badval) { + assert false, '${badval} must not be decoded to BarAlias' + } else { + assert true + } + } +} + fn test_string_decode_fails() { if _ := json.decode[Bar]('"d"') { assert false diff --git a/vlib/x/json2/tests/encode_test.v b/vlib/x/json2/tests/encode_test.v index 4e93fb676..815359fb3 100644 --- a/vlib/x/json2/tests/encode_test.v +++ b/vlib/x/json2/tests/encode_test.v @@ -9,8 +9,9 @@ type FloatAlias = f64 enum TestEnum { a - b + b @[json: 'BBB'] c = 10 + d @[badattr: 'bad'; foobar] } type EnumAlias = TestEnum @@ -122,6 +123,11 @@ fn test_enums() { assert json.encode(EnumAlias(TestEnum.c)) == '"c"' assert json.encode(TestEnum.c, enum_as_int: true) == '10' assert json.encode(EnumAlias(TestEnum.c), enum_as_int: true) == '10' + assert json.encode(TestEnum.b) == '"BBB"' + assert json.encode(EnumAlias(TestEnum.b)) == '"BBB"' + // Ensure that only `json: ` attrs is applied + assert json.encode(TestEnum.d) == '"d"' + assert json.encode(EnumAlias(TestEnum.d)) == '"d"' } fn test_sumtypes() { -- 2.39.5