Skip to content

Commit a6576be

Browse files
committed
json: fix encoding of structs with pointers; add test
1 parent ea8b30f commit a6576be

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

vlib/json/json_test.v

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,22 @@ fn test_encode_alias_field() {
508508
println(s)
509509
assert s == '{"sub":{"a":1}}'
510510
}
511+
512+
//
513+
514+
struct APrice {}
515+
516+
struct Association {
517+
association &Association = unsafe { nil }
518+
price APrice
519+
}
520+
521+
fn test_encoding_struct_with_pointers() {
522+
value := Association{
523+
association: &Association{
524+
price: APrice{}
525+
}
526+
price: APrice{}
527+
}
528+
assert json.encode(value) == '{"association":{"price":{}},"price":{}}'
529+
}

vlib/v/gen/c/json.v

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,14 @@ fn (mut g Gen) gen_struct_enc_dec(type_info ast.TypeInfo, styp string, mut enc s
482482
// it has to be encoded as a unix timestamp number
483483
enc.writeln('\tcJSON_AddItemToObject(o, "$name", json__encode_u64(val.${c_name(field.name)}._v_unix));')
484484
} else {
485-
enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.${c_name(field.name)}));\n')
485+
if !field.typ.is_real_pointer() {
486+
enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.${c_name(field.name)}));\n')
487+
} else {
488+
sptr_value := 'val.${c_name(field.name)}'
489+
enc.writeln('\tif ($sptr_value != 0) {')
490+
enc.writeln('\t\tcJSON_AddItemToObject(o, "$name", ${enc_name}(*$sptr_value));')
491+
enc.writeln('\t}\n')
492+
}
486493
}
487494
}
488495
}
@@ -499,7 +506,8 @@ fn gen_js_get(styp string, tmp string, name string, mut dec strings.Builder, is_
499506

500507
fn gen_js_get_opt(dec_name string, field_type string, styp string, tmp string, name string, mut dec strings.Builder, is_required bool) {
501508
gen_js_get(styp, tmp, name, mut dec, is_required)
502-
dec.writeln('\t${option_name}_$field_type $tmp;')
509+
value_field_type := field_type.trim_right('*')
510+
dec.writeln('\t${option_name}_$value_field_type $tmp;')
503511
dec.writeln('\tif (jsonroot_$tmp) {')
504512
dec.writeln('\t\t$tmp = ${dec_name}(jsonroot_$tmp);')
505513
dec.writeln('\t\tif (${tmp}.state != 0) {')
@@ -509,13 +517,14 @@ fn gen_js_get_opt(dec_name string, field_type string, styp string, tmp string, n
509517
}
510518

511519
fn js_enc_name(typ string) string {
512-
suffix := if typ.ends_with('*') { typ.replace('*', '') } else { typ }
520+
suffix := if typ.ends_with('*') { typ.trim_right('*') } else { typ }
513521
name := 'json__encode_$suffix'
514522
return util.no_dots(name)
515523
}
516524

517525
fn js_dec_name(typ string) string {
518-
name := 'json__decode_$typ'
526+
suffix := if typ.ends_with('*') { typ.trim_right('*') } else { typ }
527+
name := 'json__decode_$suffix'
519528
return util.no_dots(name)
520529
}
521530

0 commit comments

Comments
 (0)