Skip to content

Commit 525c5e2

Browse files
authored
x.json2: add json2.map_from(t T) (#16797)
1 parent 2c78078 commit 525c5e2

File tree

3 files changed

+177
-17
lines changed

3 files changed

+177
-17
lines changed

vlib/x/json2/decode_struct_test.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ fn test_types() {
7373
assert json.decode[StructType[int]]('{"val": 0}')!.val == 0
7474
assert json.decode[StructType[int]]('{"val": 1}')!.val == 1
7575
assert json.decode[StructType[int]]('{"val": 2}')!.val == 2
76-
assert json.decode[StructType[int]]('{"val": "true"}')!.val == 1
76+
assert json.decode[StructType[int]]('{"val": "true"}')!.val == 0
7777
assert json.decode[StructType[int]]('{"val": "false"}')!.val == 0
7878
assert json.decode[StructType[int]]('{"val": true}')!.val == 1
7979
assert json.decode[StructType[int]]('{"val": false}')!.val == 0

vlib/x/json2/json2.v

Lines changed: 99 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,42 @@ pub fn encode_pretty[T](typed_data T) string {
108108
return raw_decoded.prettify_json_str()
109109
}
110110

111+
// i8 - TODO
112+
pub fn (f Any) i8() i8 {
113+
match f {
114+
i8 {
115+
return f
116+
}
117+
i16, int, i64, u8, u16, u32, u64, f32, f64, bool {
118+
return i8(f)
119+
}
120+
string {
121+
return f.i8()
122+
}
123+
else {
124+
return 0
125+
}
126+
}
127+
}
128+
129+
// i16 - TODO
130+
pub fn (f Any) i16() i16 {
131+
match f {
132+
i16 {
133+
return f
134+
}
135+
i8, int, i64, u8, u16, u32, u64, f32, f64, bool {
136+
return i16(f)
137+
}
138+
string {
139+
return f.i16()
140+
}
141+
else {
142+
return 0
143+
}
144+
}
145+
}
146+
111147
// int uses `Any` as an integer.
112148
pub fn (f Any) int() int {
113149
match f {
@@ -118,9 +154,6 @@ pub fn (f Any) int() int {
118154
return int(f)
119155
}
120156
string {
121-
if f == 'false' || f == 'true' {
122-
return int(f.bool())
123-
}
124157
return f.int()
125158
}
126159
else {
@@ -139,9 +172,6 @@ pub fn (f Any) i64() i64 {
139172
return i64(f)
140173
}
141174
string {
142-
if f == 'false' || f == 'true' {
143-
return i64(f.bool())
144-
}
145175
return f.i64()
146176
}
147177
else {
@@ -160,9 +190,6 @@ pub fn (f Any) u64() u64 {
160190
return u64(f)
161191
}
162192
string {
163-
if f == 'false' || f == 'true' {
164-
return u64(f.bool())
165-
}
166193
return f.u64()
167194
}
168195
else {
@@ -181,9 +208,6 @@ pub fn (f Any) f32() f32 {
181208
return f32(f)
182209
}
183210
string {
184-
if f == 'false' || f == 'true' {
185-
return f32(f.bool())
186-
}
187211
return f.f32()
188212
}
189213
else {
@@ -202,9 +226,6 @@ pub fn (f Any) f64() f64 {
202226
return f64(f)
203227
}
204228
string {
205-
if f == 'false' || f == 'true' {
206-
return f64(f.bool())
207-
}
208229
return f.f64()
209230
}
210231
else {
@@ -220,8 +241,14 @@ pub fn (f Any) bool() bool {
220241
return f
221242
}
222243
string {
244+
if f == 'false' {
245+
return false
246+
}
247+
if f == 'true' {
248+
return true
249+
}
223250
if f.len > 0 {
224-
return f != '0' && f != '0.0' && f != 'false'
251+
return f != '0' && f != '0.0'
225252
} else {
226253
return false
227254
}
@@ -309,3 +336,59 @@ pub fn (f Any) to_time() !time.Time {
309336
}
310337
}
311338
}
339+
340+
fn map_from[T](t T) map[string]Any {
341+
mut m := map[string]Any{}
342+
$if T is $Struct {
343+
$for field in T.fields {
344+
value := t.$(field.name)
345+
346+
$if field.is_array {
347+
mut arr := []Any{}
348+
for variable in value {
349+
arr << Any(variable)
350+
}
351+
m[field.name] = arr
352+
arr.clear()
353+
} $else $if field.is_struct {
354+
m[field.name] = map_from(value)
355+
} $else $if field.is_map {
356+
// TODO
357+
} $else $if field.is_alias {
358+
// TODO
359+
} $else $if field.is_option {
360+
// TODO
361+
} $else {
362+
// TODO improve memory usage when convert
363+
$if field.typ is string {
364+
m[field.name] = value.str()
365+
} $else $if field.typ is bool {
366+
m[field.name] = t.$(field.name).str().bool()
367+
} $else $if field.typ is i8 {
368+
m[field.name] = t.$(field.name).str().i8()
369+
} $else $if field.typ is i16 {
370+
m[field.name] = t.$(field.name).str().i16()
371+
} $else $if field.typ is int {
372+
m[field.name] = t.$(field.name).str().int()
373+
} $else $if field.typ is i64 {
374+
m[field.name] = t.$(field.name).str().i64()
375+
} $else $if field.typ is f32 {
376+
m[field.name] = t.$(field.name).str().f32()
377+
} $else $if field.typ is f64 {
378+
m[field.name] = t.$(field.name).str().f64()
379+
} $else $if field.typ is u8 {
380+
m[field.name] = t.$(field.name).str().u8()
381+
} $else $if field.typ is u16 {
382+
m[field.name] = t.$(field.name).str().u16()
383+
} $else $if field.typ is u32 {
384+
m[field.name] = t.$(field.name).str().u32()
385+
} $else $if field.typ is u64 {
386+
m[field.name] = t.$(field.name).str().u64()
387+
} $else {
388+
// return error("The type of `${field.name}` can't be decoded. Please open an issue at https://github.com/vlang/v/issues/new/choose")
389+
}
390+
}
391+
}
392+
}
393+
return m
394+
}

vlib/x/json2/json2_test.v

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,80 @@ fn test_character_unescape() {
4444
assert lines['quotes'] or { 0 }.str() == '"quotes"'
4545
assert lines['slash'] or { 0 }.str() == '/dev/null'
4646
}
47+
48+
struct StructType[T] {
49+
mut:
50+
val T
51+
}
52+
53+
fn test_struct_with_bool_to_map() {
54+
array_of_struct := [StructType[bool]{
55+
val: true
56+
}, StructType[bool]{
57+
val: false
58+
}]
59+
60+
mut array_of_map := []json.Any{}
61+
62+
for variable in array_of_struct {
63+
array_of_map << json.map_from(variable)
64+
}
65+
66+
assert array_of_map.str() == '[{"val":true},{"val":false}]'
67+
}
68+
69+
fn test_struct_with_string_to_map() {
70+
array_of_struct := [StructType[string]{
71+
val: 'true'
72+
}, StructType[string]{
73+
val: 'false'
74+
}]
75+
76+
mut array_of_map := []json.Any{}
77+
78+
for variable in array_of_struct {
79+
array_of_map << json.map_from(variable)
80+
}
81+
82+
assert array_of_map.str() == '[{"val":"true"},{"val":"false"}]'
83+
}
84+
85+
fn test_struct_with_array_to_map() {
86+
array_of_struct := [StructType[[]bool]{
87+
val: [false, true]
88+
}, StructType[[]bool]{
89+
val: [true, false]
90+
}]
91+
92+
mut array_of_map := []json.Any{}
93+
94+
for variable in array_of_struct {
95+
array_of_map << json.map_from(variable)
96+
}
97+
98+
assert array_of_map.str() == '[{"val":[false,true]},{"val":[true,false]}]'
99+
}
100+
101+
fn test_struct_with_number_to_map() {
102+
assert json.map_from(StructType[string]{'3'}).str() == '{"val":"3"}'
103+
assert json.map_from(StructType[bool]{true}).str() == '{"val":true}'
104+
assert json.map_from(StructType[i8]{3}).str() == '{"val":3}'
105+
assert json.map_from(StructType[i16]{3}).str() == '{"val":3}'
106+
assert json.map_from(StructType[int]{3}).str() == '{"val":3}'
107+
assert json.map_from(StructType[i64]{3}).str() == '{"val":3}'
108+
assert json.map_from(StructType[i8]{-3}).str() == '{"val":-3}'
109+
assert json.map_from(StructType[i16]{i16(-3)}).str() == '{"val":-3}'
110+
assert json.map_from(StructType[int]{-3}).str() == '{"val":-3}'
111+
assert json.map_from(StructType[i64]{-3}).str() == '{"val":-3}'
112+
assert json.map_from(StructType[f32]{3.0}).str() == '{"val":3.0}'
113+
assert json.map_from(StructType[f64]{3.0}).str() == '{"val":3.0}'
114+
assert json.map_from(StructType[u8]{3}).str() == '{"val":3}'
115+
assert json.map_from(StructType[u16]{3}).str() == '{"val":3}'
116+
assert json.map_from(StructType[u32]{3}).str() == '{"val":3}'
117+
assert json.map_from(StructType[u64]{3}).str() == '{"val":3}'
118+
}
119+
120+
fn test_struct_with_struct_to_map() {
121+
assert json.map_from(StructType[StructType[string]]{StructType[string]{'3'}}).str() == '{"val":{"val":"3"}}'
122+
assert json.map_from(StructType[StructType[int]]{StructType[int]{3}}).str() == '{"val":{"val":3}}'
123+
}

0 commit comments

Comments
 (0)