Skip to content

Commit eb57746

Browse files
authored
x.json2: allow parsing a value from a multidimensional array in map_from (#22442)
1 parent c16cde7 commit eb57746

File tree

2 files changed

+71
-19
lines changed

2 files changed

+71
-19
lines changed

vlib/x/json2/json2.v

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,16 @@ pub fn map_from[T](t T) map[string]Any {
260260
value := t.$(field.name)
261261

262262
$if field.is_array {
263-
mut arr := []Any{}
264-
for variable in value {
265-
arr << Any(variable)
263+
mut top_arr := unsafe { []Any{len: t.$(field.name).len} }
264+
for idx, variable in value {
265+
$if variable is $array {
266+
top_arr[idx] = flatten_array(variable)
267+
} $else {
268+
top_arr[idx] = variable
269+
}
266270
}
267-
m[field.name] = arr
268-
arr.clear()
271+
m[field.name] = top_arr
272+
top_arr.clear()
269273
} $else $if field.is_struct {
270274
m[field.name] = map_from(value)
271275
} $else $if field.is_map {
@@ -275,33 +279,33 @@ pub fn map_from[T](t T) map[string]Any {
275279
} $else $if field.is_option {
276280
// TODO
277281
} $else {
278-
// TODO: improve memory usage when convert
282+
// TODO: simplify check of type & improve memory usage when convert
279283
$if field.typ is string {
280-
m[field.name] = value.str()
284+
m[field.name] = value
281285
} $else $if field.typ is bool {
282-
m[field.name] = t.$(field.name).str().bool()
286+
m[field.name] = t.$(field.name)
283287
} $else $if field.typ is i8 {
284-
m[field.name] = t.$(field.name).str().i8()
288+
m[field.name] = t.$(field.name)
285289
} $else $if field.typ is i16 {
286-
m[field.name] = t.$(field.name).str().i16()
290+
m[field.name] = t.$(field.name)
287291
} $else $if field.typ is i32 {
288-
m[field.name] = t.$(field.name).str().i32()
292+
m[field.name] = t.$(field.name)
289293
} $else $if field.typ is int {
290-
m[field.name] = t.$(field.name).str().int()
294+
m[field.name] = t.$(field.name)
291295
} $else $if field.typ is i64 {
292-
m[field.name] = t.$(field.name).str().i64()
296+
m[field.name] = t.$(field.name)
293297
} $else $if field.typ is f32 {
294-
m[field.name] = t.$(field.name).str().f32()
298+
m[field.name] = t.$(field.name)
295299
} $else $if field.typ is f64 {
296-
m[field.name] = t.$(field.name).str().f64()
300+
m[field.name] = t.$(field.name)
297301
} $else $if field.typ is u8 {
298-
m[field.name] = t.$(field.name).str().u8()
302+
m[field.name] = t.$(field.name)
299303
} $else $if field.typ is u16 {
300-
m[field.name] = t.$(field.name).str().u16()
304+
m[field.name] = t.$(field.name)
301305
} $else $if field.typ is u32 {
302-
m[field.name] = t.$(field.name).str().u32()
306+
m[field.name] = t.$(field.name)
303307
} $else $if field.typ is u64 {
304-
m[field.name] = t.$(field.name).str().u64()
308+
m[field.name] = t.$(field.name)
305309
} $else {
306310
// return error("The type of `${field.name}` can't be decoded. Please open an issue at https://github.com/vlang/v/issues/new/choose")
307311
}
@@ -310,3 +314,21 @@ pub fn map_from[T](t T) map[string]Any {
310314
}
311315
return m
312316
}
317+
318+
// flatten_array convert a array of values to array of Any
319+
@[inline]
320+
fn flatten_array[T](t []T) []Any {
321+
$if t !is $array {
322+
return Any(t)
323+
} $else {
324+
mut arr := []Any{}
325+
for variable in t {
326+
$if variable is $array {
327+
arr << flatten_array(variable)
328+
} $else {
329+
arr << Any(variable)
330+
}
331+
}
332+
return arr
333+
}
334+
}

vlib/x/json2/tests/json2_test.v

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,36 @@ fn test_struct_with_array_to_map() {
9898
assert array_of_map.str() == '[{"val":[false,true]},{"val":[true,false]}]'
9999
}
100100

101+
fn test_struct_with_array_of_arrays_to_map() {
102+
array_of_struct := [
103+
StructType[[][]bool]{
104+
val: [[true, false], [true, false]]
105+
},
106+
StructType[[][]bool]{
107+
val: [[false, true], [false, true]]
108+
},
109+
]
110+
mut array_of_map := []json.Any{}
111+
for variable in array_of_struct {
112+
array_of_map << json.map_from(variable)
113+
}
114+
assert array_of_map.str() == '[{"val":[[true,false],[true,false]]},{"val":[[false,true],[false,true]]}]'
115+
116+
array_of_struct_int := [
117+
StructType[[][]int]{
118+
val: [[1, 0], [1, 0]]
119+
},
120+
StructType[[][]int]{
121+
val: [[0, 1], [0, 1]]
122+
},
123+
]
124+
mut array_of_map_int := []json.Any{}
125+
for variable in array_of_struct_int {
126+
array_of_map_int << json.map_from(variable)
127+
}
128+
assert array_of_map_int.str() == '[{"val":[[1,0],[1,0]]},{"val":[[0,1],[0,1]]}]'
129+
}
130+
101131
fn test_struct_with_number_to_map() {
102132
assert json.map_from(StructType[string]{'3'}).str() == '{"val":"3"}'
103133
assert json.map_from(StructType[bool]{true}).str() == '{"val":true}'

0 commit comments

Comments
 (0)