diff --git a/vlib/json/json_encode_struct_with_optional_field_test.v b/vlib/json/json_encode_struct_with_optional_field_test.v new file mode 100644 index 0000000000..100eb89c25 --- /dev/null +++ b/vlib/json/json_encode_struct_with_optional_field_test.v @@ -0,0 +1,20 @@ +import json + +struct Foo { + name string + num ?int +} + +fn test_json_encode_struct_with_optional_field() { + f1 := Foo{ + name: 'hello' + } + ret1 := json.encode(f1) + println(ret1) + assert ret1 == '{"name":"hello","num":null}' + + f2 := Foo{'hello', 22} + ret2 := json.encode(f2) + println(ret2) + assert ret2 == '{"name":"hello","num":22}' +} diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 6180e9aa6f..20454ab8cb 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -1061,7 +1061,11 @@ fn (mut g Gen) optional_type_name(t ast.Type) (string, string) { } fn (mut g Gen) result_type_name(t ast.Type) (string, string) { - base := g.base_type(t) + mut base := g.base_type(t) + if t.has_flag(.optional) { + g.register_optional(t) + base = '_option_' + base + } mut styp := '' sym := g.table.sym(t) if sym.language == .c && sym.kind == .struct_ { diff --git a/vlib/v/gen/c/json.v b/vlib/v/gen/c/json.v index b6fc0ddb2a..84fa2d877f 100644 --- a/vlib/v/gen/c/json.v +++ b/vlib/v/gen/c/json.v @@ -26,7 +26,7 @@ import strings fn (mut g Gen) gen_json_for_type(typ ast.Type) { utyp := g.unwrap_generic(typ).set_nr_muls(0) sym := g.table.sym(utyp) - if is_js_prim(sym.name) || sym.kind == .enum_ { + if (is_js_prim(sym.name) && !utyp.has_flag(.optional)) || sym.kind == .enum_ { return } g.json_types << utyp @@ -54,10 +54,14 @@ fn (mut g Gen) gen_jsons() { mut init_styp := '${styp} res' if sym.kind == .struct_ { init_styp += ' = ' - init_styp += g.expr_string(ast.Expr(ast.StructInit{ + g.set_current_pos_as_last_stmt_pos() + pos := g.out.len + g.write(init_styp) + g.expr(ast.Expr(ast.StructInit{ typ: utyp typ_str: styp })) + init_styp = g.out.cut_to(pos).trim_space() } dec.writeln(' @@ -144,6 +148,8 @@ ${enc_fn_dec} { verror('json: ${sym.name} is not a sumtype') } g.gen_sumtype_enc_dec(sym, mut enc, mut dec) + } else if utyp.has_flag(.optional) { + g.gen_option_enc_dec(utyp, mut enc, mut dec) } else { enc.writeln('\to = cJSON_CreateObject();') // Structs. Range through fields @@ -162,6 +168,15 @@ ${enc_fn_dec} { } } +fn (mut g Gen) gen_option_enc_dec(typ ast.Type, mut enc strings.Builder, mut dec strings.Builder) { + enc.writeln('\tif (val.state == 2) {') + enc.writeln('\t\treturn cJSON_CreateNull();') + enc.writeln('\t}') + type_str := g.typ(typ.clear_flag(.optional)) + encode_name := js_enc_name(type_str) + enc.writeln('\to = ${encode_name}(*(${type_str}*)val.data);') +} + [inline] fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder, mut dec strings.Builder) { info := sym.info as ast.SumType