Skip to content

Commit

Permalink
json: fix decoding of structs with embeds (#22264)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Sep 21, 2024
1 parent 7af312c commit 651a116
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
28 changes: 28 additions & 0 deletions vlib/json/json_decode_embed_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module main

import json

struct Json2 {
inner []f64
}

struct Json {
Json2
test f64
}

fn test_main() {
str := '{
"inner": [1, 2, 3, 4, 5],
"test": 1.0
}'
data := json.decode(Json, str) or {
eprintln('Failed to decode json, error: ${err}')
return
}
println(data)
assert data.inner.len == 5
assert data.inner[0] == 1.0
assert data.inner[4] == 5.0
assert data.test == 1.0
}
27 changes: 23 additions & 4 deletions vlib/v/gen/c/json.v
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ ${enc_fn_dec} {
}
} else if psym.info is ast.Struct {
enc.writeln('\to = cJSON_CreateObject();')
g.gen_struct_enc_dec(utyp, psym.info, ret_styp, mut enc, mut dec)
g.gen_struct_enc_dec(utyp, psym.info, ret_styp, mut enc, mut dec, '')
} else if psym.kind == .enum_ {
g.gen_enum_enc_dec(utyp, psym, mut enc, mut dec)
} else if psym.kind == .sum_type {
Expand Down Expand Up @@ -201,7 +201,7 @@ ${enc_fn_dec} {
if sym.info !is ast.Struct {
verror('json: ${sym.name} is not struct')
}
g.gen_struct_enc_dec(utyp, sym.info, ret_styp, mut enc, mut dec)
g.gen_struct_enc_dec(utyp, sym.info, ret_styp, mut enc, mut dec, '')
}
// cJSON_delete
dec.writeln('\t${result_name}_${ret_styp} ret;')
Expand Down Expand Up @@ -606,7 +606,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st

@[inline]
fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp string, mut enc strings.Builder,
mut dec strings.Builder) {
mut dec strings.Builder, embed_prefix string) {
info := type_info as ast.Struct
for field in info.fields {
mut name := field.name
Expand Down Expand Up @@ -646,7 +646,12 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
field_type := g.typ(field.typ)
field_sym := g.table.sym(field.typ)
op := if utyp.is_ptr() { '->' } else { '.' }
prefix := if utyp.has_flag(.option) { '(*(${g.base_type(utyp)}*)res.data)' } else { 'res' }
embed_member := if embed_prefix.len > 0 { '.${embed_prefix}' } else { '' }
prefix := if utyp.has_flag(.option) {
'(*(${g.base_type(utyp)}*)res${embed_member}.data)'
} else {
'res${embed_member}'
}
// First generate decoding
if is_raw {
if field.typ.has_flag(.option) {
Expand Down Expand Up @@ -757,6 +762,17 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
dec.writeln('\t}')
}
} else {
// embeded
if name.len > 0 && name[0].is_capital() && field_sym.info is ast.Struct {
for embed in info.embeds {
if embed == int(field.typ) {
g.gen_struct_enc_dec(field.typ, g.table.sym(field.typ).info,
styp, mut enc, mut dec, name)
break
}
}
continue
}
tmp := g.new_tmp_var()
gen_js_get_opt(dec_name, field_type, styp, tmp, name, mut dec, is_required)
dec.writeln('\tif (jsonroot_${tmp}) {')
Expand All @@ -781,6 +797,9 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st
dec.writeln('\t}')
}
}
if embed_prefix.len > 0 {
return
}
// Encoding
mut enc_name := js_enc_name(field_type)
prefix_enc := if utyp.has_flag(.option) {
Expand Down

0 comments on commit 651a116

Please sign in to comment.