From de3b184b0135ffb6a4c7097b024149ba96e00159 Mon Sep 17 00:00:00 2001 From: Hitalo Souza Date: Fri, 6 Dec 2024 13:47:17 -0400 Subject: [PATCH] json2.decoder2: prepare decoder in json2 to be replaced by json2.decode2 (#23078) --- cmd/tools/vls.v | 4 ++-- vlib/v/slow_tests/valgrind/import_x_json2.v | 2 +- vlib/x/json2/README.md | 6 +++--- vlib/x/json2/decoder.v | 10 ++++------ vlib/x/json2/decoder2/decode.v | 19 +++++++++++++++++-- vlib/x/json2/decoder2/decode_sumtype.v | 12 +++++++++--- vlib/x/json2/decoder2/decoder_deprecated.v | 8 ++++++++ .../json2/decoder2/tests/json_sumtype_test.v | 1 - vlib/x/json2/decoder_deprecated.v | 17 +++++++++++++++++ vlib/x/json2/encoder.v | 2 +- vlib/x/json2/tests/decode_map_test.v | 4 +--- 11 files changed, 63 insertions(+), 22 deletions(-) create mode 100644 vlib/x/json2/decoder2/decoder_deprecated.v diff --git a/cmd/tools/vls.v b/cmd/tools/vls.v index d76a6ba88030f1..d66b520abd8191 100644 --- a/cmd/tools/vls.v +++ b/cmd/tools/vls.v @@ -79,7 +79,7 @@ fn (upd VlsUpdater) check_or_create_vls_folder() ! { fn (upd VlsUpdater) manifest_config() !map[string]json2.Any { manifest_buf := os.read_file(vls_manifest_path) or { '{}' } - manifest_contents := json2.raw_decode(manifest_buf)!.as_map() + manifest_contents := json2.decode[json2.Any](manifest_buf)!.as_map() return manifest_contents } @@ -168,7 +168,7 @@ fn (upd VlsUpdater) download_prebuilt() ! { upd.log('Finding prebuilt executables from GitHub release..') resp := http.get('https://api.github.com/repos/vlang/vls/releases')! - releases_json := json2.raw_decode(resp.body)!.arr() + releases_json := json2.decode[json2.Any](resp.body)!.arr() if releases_json.len == 0 { return error('Unable to fetch latest VLS release data: No releases found.') } diff --git a/vlib/v/slow_tests/valgrind/import_x_json2.v b/vlib/v/slow_tests/valgrind/import_x_json2.v index 90b93d5afb450a..62e9a2f26efe33 100644 --- a/vlib/v/slow_tests/valgrind/import_x_json2.v +++ b/vlib/v/slow_tests/valgrind/import_x_json2.v @@ -2,5 +2,5 @@ import x.json2 fn main() { x := '[[],[],[]]' - println(json2.raw_decode(x)!) + println(json2.decode[json2.Any](x)!) } diff --git a/vlib/x/json2/README.md b/vlib/x/json2/README.md index a7e3017635e6ba..39facf754e128e 100644 --- a/vlib/x/json2/README.md +++ b/vlib/x/json2/README.md @@ -77,7 +77,7 @@ fn main() { resp := http.get('https://reqres.in/api/products/1')! // This returns an Any type - raw_product := json2.raw_decode(resp.body)! + raw_product := json2.decode[json2.Any](resp.body)! } ``` @@ -90,7 +90,7 @@ import net.http fn main() { resp := http.get('https://reqres.in/api/products/1')! - raw_product := json2.raw_decode(resp.body)! + raw_product := json2.decode[json2.Any](resp.body)! product := raw_product.as_map() data := product['data'] as map[string]json2.Any @@ -174,4 +174,4 @@ json2.encode_value(, mut buffer)! sb.write(buffer)! unsafe { buffer.free() } -``` \ No newline at end of file +``` diff --git a/vlib/x/json2/decoder.v b/vlib/x/json2/decoder.v index 9c22e1d0349488..5ffa6db122783a 100644 --- a/vlib/x/json2/decoder.v +++ b/vlib/x/json2/decoder.v @@ -60,16 +60,13 @@ fn new_parser(srce string, convert_type bool) Parser { // decode is a generic function that decodes a JSON string into the target type. pub fn decode[T](src string) !T { + $if T is Any { + return raw_decode(src)! + } res := raw_decode(src)!.as_map() return decode_struct[T](T{}, res) } -// decode_array is a generic function that decodes a JSON string into the array target type. -pub fn decode_array[T](src string) ![]T { - res := raw_decode(src)!.as_map() - return decode_struct_array(T{}, res) -} - // decode_struct_array is a generic function that decodes a JSON map into array struct T. fn decode_struct_array[T](_ T, res map[string]Any) ![]T { $if T is $struct { @@ -428,6 +425,7 @@ fn (mut p Parser) decode_array() !Any { return Any(items) } +@[deprecated_after: '2025-03-18'] fn (mut p Parser) decode_object() !Any { mut fields := map[string]Any{} p.next_with_err()! diff --git a/vlib/x/json2/decoder2/decode.v b/vlib/x/json2/decoder2/decode.v index 4547c4e79612ae..81379b65a08eb6 100644 --- a/vlib/x/json2/decoder2/decode.v +++ b/vlib/x/json2/decoder2/decode.v @@ -777,10 +777,25 @@ fn (mut decoder Decoder) decode_value[T](mut val T) ! { } if current_field_info.value.is_raw { - $if field.typ is $enum { + $if field.unaliased_typ is $enum { // workaround to avoid the error: enums can only be assigned `int` values return error('`raw` attribute cannot be used with enum fields') - } $else $if field.typ is string || field.typ is ?string { + } $else $if field.typ is ?string { + position := decoder.current_node.value.position + end := position + decoder.current_node.value.length + + val.$(field.name) = decoder.json[position..end] + decoder.current_node = decoder.current_node.next + + for { + if decoder.current_node == unsafe { nil } + || decoder.current_node.value.position + decoder.current_node.value.length >= end { + break + } + + decoder.current_node = decoder.current_node.next + } + } $else $if field.typ is string { position := decoder.current_node.value.position end := position + decoder.current_node.value.length diff --git a/vlib/x/json2/decoder2/decode_sumtype.v b/vlib/x/json2/decoder2/decode_sumtype.v index 87dd6a9796b888..2dff869112d973 100644 --- a/vlib/x/json2/decoder2/decode_sumtype.v +++ b/vlib/x/json2/decoder2/decode_sumtype.v @@ -6,9 +6,15 @@ fn (mut decoder Decoder) get_decoded_sumtype_workaround[T](initialized_sumtype T $if initialized_sumtype is $sumtype { $for v in initialized_sumtype.variants { if initialized_sumtype is v { - mut val := initialized_sumtype - decoder.decode_value(mut val)! - return T(val) + $if v is $array { + mut val := initialized_sumtype.clone() + decoder.decode_value(mut val)! + return T(val) + } $else { + mut val := initialized_sumtype + decoder.decode_value(mut val)! + return T(val) + } } } } diff --git a/vlib/x/json2/decoder2/decoder_deprecated.v b/vlib/x/json2/decoder2/decoder_deprecated.v new file mode 100644 index 00000000000000..23e649579481ae --- /dev/null +++ b/vlib/x/json2/decoder2/decoder_deprecated.v @@ -0,0 +1,8 @@ +module decoder2 + +// decode_array is a generic function that decodes a JSON string into the array target type. +@[deprecated: 'use `decode` instead'] +@[deprecated_after: '2025-03-18'] +pub fn decode_array[T](src string) !T { + return decode[T](src) +} diff --git a/vlib/x/json2/decoder2/tests/json_sumtype_test.v b/vlib/x/json2/decoder2/tests/json_sumtype_test.v index 3c16c2d202e92c..4ff7e07215b42e 100644 --- a/vlib/x/json2/decoder2/tests/json_sumtype_test.v +++ b/vlib/x/json2/decoder2/tests/json_sumtype_test.v @@ -1,6 +1,5 @@ import x.json2.decoder2 as json import x.json2 -import time type Prices = Price | []Price diff --git a/vlib/x/json2/decoder_deprecated.v b/vlib/x/json2/decoder_deprecated.v index dfa95f2c61b993..9120536beb69cc 100644 --- a/vlib/x/json2/decoder_deprecated.v +++ b/vlib/x/json2/decoder_deprecated.v @@ -7,11 +7,13 @@ pub struct DecodeError { } // code returns the error code of DecodeError +@[deprecated_after: '2025-03-18'] pub fn (err DecodeError) code() int { return 3 } // msg returns the message of the DecodeError +@[deprecated_after: '2025-03-18'] pub fn (err DecodeError) msg() string { return format_message(err.message, err.line, err.column) } @@ -23,11 +25,13 @@ pub struct InvalidTokenError { } // code returns the error code of the InvalidTokenError +@[deprecated_after: '2025-03-18'] pub fn (err InvalidTokenError) code() int { return 2 } // msg returns the message of the InvalidTokenError +@[deprecated_after: '2025-03-18'] pub fn (err InvalidTokenError) msg() string { footer_text := if err.expected != .none { ', expecting `${err.expected}`' } else { '' } return format_message('invalid token `${err.token.kind}`${footer_text}', err.token.line, @@ -41,11 +45,13 @@ pub struct UnknownTokenError { } // code returns the error code of the UnknownTokenError +@[deprecated_after: '2025-03-18'] pub fn (err UnknownTokenError) code() int { return 1 } // msg returns the error message of the UnknownTokenError +@[deprecated_after: '2025-03-18'] pub fn (err UnknownTokenError) msg() string { return format_message("unknown token '${err.token.lit}' when decoding ${err.kind}.", err.token.line, err.token.full_col()) @@ -68,12 +74,15 @@ pub fn raw_decode(src string) !Any { } // Same with `raw_decode`, but skips the type conversion for certain types when decoding a certain value. +@[deprecated: 'use `decode[json.Any]` instead'] +@[deprecated_after: '2025-03-18'] pub fn fast_raw_decode(src string) !Any { mut p := new_parser(src, false) return p.decode() } // decode - decodes provided JSON +@[deprecated_after: '2025-03-18'] pub fn (mut p Parser) decode() !Any { p.next() p.next_with_err()! @@ -85,3 +94,11 @@ pub fn (mut p Parser) decode() !Any { } return fi } + +// decode_array is a generic function that decodes a JSON string into the array target type. +@[deprecated: 'use `decode` instead'] +@[deprecated_after: '2025-03-18'] +pub fn decode_array[T](src string) ![]T { + res := raw_decode(src)!.as_map() + return decode_struct_array(T{}, res) +} diff --git a/vlib/x/json2/encoder.v b/vlib/x/json2/encoder.v index 9795b3c636f536..778f7ae47acac3 100644 --- a/vlib/x/json2/encoder.v +++ b/vlib/x/json2/encoder.v @@ -100,7 +100,7 @@ fn encode_array[T](val []T) string { // encode_pretty ... pub fn encode_pretty[T](typed_data T) string { encoded := encode(typed_data) - raw_decoded := raw_decode(encoded) or { 0 } + raw_decoded := decode[Any](encoded) or { 0 } return raw_decoded.prettify_json_str() } diff --git a/vlib/x/json2/tests/decode_map_test.v b/vlib/x/json2/tests/decode_map_test.v index 5a9aecb80d31fc..6f37052e659f8b 100644 --- a/vlib/x/json2/tests/decode_map_test.v +++ b/vlib/x/json2/tests/decode_map_test.v @@ -1,5 +1,3 @@ -module main - import x.json2 const data = ' @@ -31,7 +29,7 @@ const data = ' } ' -struct Comment { +pub struct Comment { id string message string }