From a1b6360da5b5d21da207536f1810abfe34796c3b Mon Sep 17 00:00:00 2001 From: Turiiya <34311583+ttytm@users.noreply.github.com> Date: Tue, 2 Apr 2024 04:32:11 +0200 Subject: [PATCH] x.json2: add ability to decode arrays (#21163) --- vlib/x/json2/decoder.v | 33 +++++++++++++++++++++++++++++++ vlib/x/json2/tests/decoder_test.v | 24 +++++++++++++++++++--- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/vlib/x/json2/decoder.v b/vlib/x/json2/decoder.v index 5683eff4e03f27..c0a977aefab08e 100644 --- a/vlib/x/json2/decoder.v +++ b/vlib/x/json2/decoder.v @@ -249,6 +249,39 @@ fn decode_struct[T](_ T, res map[string]Any) !T { typ.$(field.name) = res[json_name]!.to_time()! } } $else $if field.is_array { + arr := res[field.name]! as []Any + match typeof(typ.$(field.name)).name { + '[]bool' { typ.$(field.name) = arr.map(it.bool()) } + '[]?bool' { typ.$(field.name) = arr.map(?bool(it.bool())) } + '[]f32' { typ.$(field.name) = arr.map(it.f32()) } + '[]?f32' { typ.$(field.name) = arr.map(?f32(it.f32())) } + '[]f64' { typ.$(field.name) = arr.map(it.f64()) } + '[]?f64' { typ.$(field.name) = arr.map(?f64(it.f64())) } + '[]i8' { typ.$(field.name) = arr.map(it.i8()) } + '[]?i8' { typ.$(field.name) = arr.map(?i8(it.i8())) } + '[]i16' { typ.$(field.name) = arr.map(it.i16()) } + '[]?i16' { typ.$(field.name) = arr.map(?i16(it.i16())) } + '[]i64' { typ.$(field.name) = arr.map(it.i64()) } + '[]?i64' { typ.$(field.name) = arr.map(?i64(it.i64())) } + '[]int' { typ.$(field.name) = arr.map(it.int()) } + '[]?int' { typ.$(field.name) = arr.map(?int(it.int())) } + '[]string' { typ.$(field.name) = arr.map(it.str()) } + '[]?string' { typ.$(field.name) = arr.map(?string(it.str())) } + // NOTE: Using `!` on `to_time()` inside the array method causes a builder error - 2024/04/01. + '[]time.Time' { typ.$(field.name) = arr.map(it.to_time() or { time.Time{} }) } + // vfmt off + '[]?time.Time' { typ.$(field.name) = arr.map(?time.Time(it.to_time() or { time.Time{} })) } + // vfmt on + '[]u8' { typ.$(field.name) = arr.map(it.u64()) } + '[]?u8' { typ.$(field.name) = arr.map(?u8(it.u64())) } + '[]u16' { typ.$(field.name) = arr.map(it.u64()) } + '[]?u16' { typ.$(field.name) = arr.map(?u16(it.u64())) } + '[]u32' { typ.$(field.name) = arr.map(it.u64()) } + '[]?u32' { typ.$(field.name) = arr.map(?u32(it.u64())) } + '[]u64' { typ.$(field.name) = arr.map(it.u64()) } + '[]?u64' { typ.$(field.name) = arr.map(?u64(it.u64())) } + else {} + } } $else $if field.is_struct { typ.$(field.name) = decode_struct(typ.$(field.name), res[field.name]!.as_map())! } $else $if field.is_alias { diff --git a/vlib/x/json2/tests/decoder_test.v b/vlib/x/json2/tests/decoder_test.v index 8532302ae1467b..ca193f6959ab48 100644 --- a/vlib/x/json2/tests/decoder_test.v +++ b/vlib/x/json2/tests/decoder_test.v @@ -83,6 +83,24 @@ fn test_raw_decode_array_invalid() { assert false } +struct Foo { + int []int + str []string + f32 []f32 + oint []?int +} + +fn test_decode_array_fields() { + input := '{"int":[0, 1], "str":["2", "3"], "f32": [4.0, 5.0], "oint": [6, null]}' + foo := json.decode[Foo](input)! + assert foo.int == [0, 1] + assert foo.str == ['2', '3'] + assert foo.f32 == [f32(4.0), 5.0] + a, b := foo.oint[0], foo.oint[1] + assert a? == 6 + assert b? == 0 +} + struct ContactItem { description string telnr string @@ -95,9 +113,9 @@ struct User { } fn test_decode_missing_comma() { - data := '{ - "name": "Frodo", - "age": 25 + data := '{ + "name": "Frodo", + "age": 25 "contact": { "description": "descr", "telnr": "+32333"