1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: fix json decode with generic array of struct (fix #18300) (#18308)

This commit is contained in:
yuyi 2023-05-30 20:25:33 +08:00 committed by GitHub
parent ac6289301c
commit 4dc338863c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 1 deletions

View File

@ -0,0 +1,44 @@
import json
struct Response[T] {
time string
cars []T
}
struct Car {
brand string
power int
}
fn string_to_response[T](text string) {
result := json.decode([]Response[T], text) or { panic(err) }
println(result)
assert result.len == 2
assert result[0].time == '12ms'
assert result[0].cars[0].brand == 'Ferrari'
assert result[0].cars[0].power == 232
assert result[0].cars[1].brand == 'Lamborghini'
assert result[0].cars[1].power == 345
assert result[1].time == '12ms'
assert result[1].cars[0].brand == 'Ferrari'
assert result[1].cars[0].power == 232
assert result[1].cars[1].brand == 'Lamborghini'
assert result[1].cars[1].power == 345
}
fn test_json_decode_with_generic_array() {
text := '[
{ "time":"12ms",
"cars":[
{"brand":"Ferrari","power":232},
{"brand":"Lamborghini", "power":345}
]},
{ "time":"12ms",
"cars":[
{"brand":"Ferrari","power":232},
{"brand":"Lamborghini", "power":345}
]}
]'
string_to_response[Car](text)
}

View File

@ -567,6 +567,42 @@ fn (mut c Checker) builtin_args(mut node ast.CallExpr, fn_name string, func ast.
*/ */
} }
fn (mut c Checker) needs_unwrap_generic_type(typ ast.Type) bool {
if typ == 0 || !typ.has_flag(.generic) {
return false
}
sym := c.table.sym(typ)
match sym.info {
ast.Struct, ast.Interface, ast.SumType {
return true
}
ast.Array {
return c.needs_unwrap_generic_type(sym.info.elem_type)
}
ast.ArrayFixed {
return c.needs_unwrap_generic_type(sym.info.elem_type)
}
ast.Map {
if c.needs_unwrap_generic_type(sym.info.key_type) {
return true
}
if c.needs_unwrap_generic_type(sym.info.value_type) {
return true
}
}
ast.Chan {
return c.needs_unwrap_generic_type(sym.info.elem_type)
}
ast.Thread {
return c.needs_unwrap_generic_type(sym.info.return_type)
}
else {
return false
}
}
return false
}
fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.Type { fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.Type {
fn_name := node.name fn_name := node.name
if fn_name == 'main' { if fn_name == 'main' {
@ -647,7 +683,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
expr := node.args[0].expr expr := node.args[0].expr
if expr is ast.TypeNode { if expr is ast.TypeNode {
mut unwrapped_typ := c.unwrap_generic(expr.typ) mut unwrapped_typ := c.unwrap_generic(expr.typ)
if c.table.sym(expr.typ).kind == .struct_ && expr.typ.has_flag(.generic) { if c.needs_unwrap_generic_type(expr.typ) {
unwrapped_typ = c.table.unwrap_generic_type(expr.typ, c.table.cur_fn.generic_names, unwrapped_typ = c.table.unwrap_generic_type(expr.typ, c.table.cur_fn.generic_names,
c.table.cur_concrete_types) c.table.cur_concrete_types)
} }