From 525c5e237ace081c056a7609a5ceb6c6268fd03f Mon Sep 17 00:00:00 2001 From: Hitalo Souza <63821277+enghitalo@users.noreply.github.com> Date: Wed, 18 Jan 2023 13:55:04 -0300 Subject: [PATCH] x.json2: add json2.map_from(t T) (#16797) --- vlib/x/json2/decode_struct_test.v | 2 +- vlib/x/json2/json2.v | 115 +++++++++++++++++++++++++----- vlib/x/json2/json2_test.v | 77 ++++++++++++++++++++ 3 files changed, 177 insertions(+), 17 deletions(-) diff --git a/vlib/x/json2/decode_struct_test.v b/vlib/x/json2/decode_struct_test.v index 56f0560cc8..6699f888cd 100644 --- a/vlib/x/json2/decode_struct_test.v +++ b/vlib/x/json2/decode_struct_test.v @@ -73,7 +73,7 @@ fn test_types() { assert json.decode[StructType[int]]('{"val": 0}')!.val == 0 assert json.decode[StructType[int]]('{"val": 1}')!.val == 1 assert json.decode[StructType[int]]('{"val": 2}')!.val == 2 - assert json.decode[StructType[int]]('{"val": "true"}')!.val == 1 + assert json.decode[StructType[int]]('{"val": "true"}')!.val == 0 assert json.decode[StructType[int]]('{"val": "false"}')!.val == 0 assert json.decode[StructType[int]]('{"val": true}')!.val == 1 assert json.decode[StructType[int]]('{"val": false}')!.val == 0 diff --git a/vlib/x/json2/json2.v b/vlib/x/json2/json2.v index eba8d4419e..19d654c8b9 100644 --- a/vlib/x/json2/json2.v +++ b/vlib/x/json2/json2.v @@ -108,6 +108,42 @@ pub fn encode_pretty[T](typed_data T) string { return raw_decoded.prettify_json_str() } +// i8 - TODO +pub fn (f Any) i8() i8 { + match f { + i8 { + return f + } + i16, int, i64, u8, u16, u32, u64, f32, f64, bool { + return i8(f) + } + string { + return f.i8() + } + else { + return 0 + } + } +} + +// i16 - TODO +pub fn (f Any) i16() i16 { + match f { + i16 { + return f + } + i8, int, i64, u8, u16, u32, u64, f32, f64, bool { + return i16(f) + } + string { + return f.i16() + } + else { + return 0 + } + } +} + // int uses `Any` as an integer. pub fn (f Any) int() int { match f { @@ -118,9 +154,6 @@ pub fn (f Any) int() int { return int(f) } string { - if f == 'false' || f == 'true' { - return int(f.bool()) - } return f.int() } else { @@ -139,9 +172,6 @@ pub fn (f Any) i64() i64 { return i64(f) } string { - if f == 'false' || f == 'true' { - return i64(f.bool()) - } return f.i64() } else { @@ -160,9 +190,6 @@ pub fn (f Any) u64() u64 { return u64(f) } string { - if f == 'false' || f == 'true' { - return u64(f.bool()) - } return f.u64() } else { @@ -181,9 +208,6 @@ pub fn (f Any) f32() f32 { return f32(f) } string { - if f == 'false' || f == 'true' { - return f32(f.bool()) - } return f.f32() } else { @@ -202,9 +226,6 @@ pub fn (f Any) f64() f64 { return f64(f) } string { - if f == 'false' || f == 'true' { - return f64(f.bool()) - } return f.f64() } else { @@ -220,8 +241,14 @@ pub fn (f Any) bool() bool { return f } string { + if f == 'false' { + return false + } + if f == 'true' { + return true + } if f.len > 0 { - return f != '0' && f != '0.0' && f != 'false' + return f != '0' && f != '0.0' } else { return false } @@ -309,3 +336,59 @@ pub fn (f Any) to_time() !time.Time { } } } + +fn map_from[T](t T) map[string]Any { + mut m := map[string]Any{} + $if T is $Struct { + $for field in T.fields { + value := t.$(field.name) + + $if field.is_array { + mut arr := []Any{} + for variable in value { + arr << Any(variable) + } + m[field.name] = arr + arr.clear() + } $else $if field.is_struct { + m[field.name] = map_from(value) + } $else $if field.is_map { + // TODO + } $else $if field.is_alias { + // TODO + } $else $if field.is_option { + // TODO + } $else { + // TODO improve memory usage when convert + $if field.typ is string { + m[field.name] = value.str() + } $else $if field.typ is bool { + m[field.name] = t.$(field.name).str().bool() + } $else $if field.typ is i8 { + m[field.name] = t.$(field.name).str().i8() + } $else $if field.typ is i16 { + m[field.name] = t.$(field.name).str().i16() + } $else $if field.typ is int { + m[field.name] = t.$(field.name).str().int() + } $else $if field.typ is i64 { + m[field.name] = t.$(field.name).str().i64() + } $else $if field.typ is f32 { + m[field.name] = t.$(field.name).str().f32() + } $else $if field.typ is f64 { + m[field.name] = t.$(field.name).str().f64() + } $else $if field.typ is u8 { + m[field.name] = t.$(field.name).str().u8() + } $else $if field.typ is u16 { + m[field.name] = t.$(field.name).str().u16() + } $else $if field.typ is u32 { + m[field.name] = t.$(field.name).str().u32() + } $else $if field.typ is u64 { + m[field.name] = t.$(field.name).str().u64() + } $else { + // return error("The type of `${field.name}` can't be decoded. Please open an issue at https://github.com/vlang/v/issues/new/choose") + } + } + } + } + return m +} diff --git a/vlib/x/json2/json2_test.v b/vlib/x/json2/json2_test.v index ae5d13b02d..74a0f0d89b 100644 --- a/vlib/x/json2/json2_test.v +++ b/vlib/x/json2/json2_test.v @@ -44,3 +44,80 @@ fn test_character_unescape() { assert lines['quotes'] or { 0 }.str() == '"quotes"' assert lines['slash'] or { 0 }.str() == '/dev/null' } + +struct StructType[T] { +mut: + val T +} + +fn test_struct_with_bool_to_map() { + array_of_struct := [StructType[bool]{ + val: true + }, StructType[bool]{ + val: false + }] + + mut array_of_map := []json.Any{} + + for variable in array_of_struct { + array_of_map << json.map_from(variable) + } + + assert array_of_map.str() == '[{"val":true},{"val":false}]' +} + +fn test_struct_with_string_to_map() { + array_of_struct := [StructType[string]{ + val: 'true' + }, StructType[string]{ + val: 'false' + }] + + mut array_of_map := []json.Any{} + + for variable in array_of_struct { + array_of_map << json.map_from(variable) + } + + assert array_of_map.str() == '[{"val":"true"},{"val":"false"}]' +} + +fn test_struct_with_array_to_map() { + array_of_struct := [StructType[[]bool]{ + val: [false, true] + }, StructType[[]bool]{ + val: [true, false] + }] + + mut array_of_map := []json.Any{} + + for variable in array_of_struct { + array_of_map << json.map_from(variable) + } + + assert array_of_map.str() == '[{"val":[false,true]},{"val":[true,false]}]' +} + +fn test_struct_with_number_to_map() { + assert json.map_from(StructType[string]{'3'}).str() == '{"val":"3"}' + assert json.map_from(StructType[bool]{true}).str() == '{"val":true}' + assert json.map_from(StructType[i8]{3}).str() == '{"val":3}' + assert json.map_from(StructType[i16]{3}).str() == '{"val":3}' + assert json.map_from(StructType[int]{3}).str() == '{"val":3}' + assert json.map_from(StructType[i64]{3}).str() == '{"val":3}' + assert json.map_from(StructType[i8]{-3}).str() == '{"val":-3}' + assert json.map_from(StructType[i16]{i16(-3)}).str() == '{"val":-3}' + assert json.map_from(StructType[int]{-3}).str() == '{"val":-3}' + assert json.map_from(StructType[i64]{-3}).str() == '{"val":-3}' + assert json.map_from(StructType[f32]{3.0}).str() == '{"val":3.0}' + assert json.map_from(StructType[f64]{3.0}).str() == '{"val":3.0}' + assert json.map_from(StructType[u8]{3}).str() == '{"val":3}' + assert json.map_from(StructType[u16]{3}).str() == '{"val":3}' + assert json.map_from(StructType[u32]{3}).str() == '{"val":3}' + assert json.map_from(StructType[u64]{3}).str() == '{"val":3}' +} + +fn test_struct_with_struct_to_map() { + assert json.map_from(StructType[StructType[string]]{StructType[string]{'3'}}).str() == '{"val":{"val":"3"}}' + assert json.map_from(StructType[StructType[int]]{StructType[int]{3}}).str() == '{"val":{"val":3}}' +}