mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
json: fix -cstrict build + optional map (#18014)
This commit is contained in:
parent
4c54f36a70
commit
c43ea09d87
22
vlib/json/json_encode_map_test.v
Normal file
22
vlib/json/json_encode_map_test.v
Normal file
@ -0,0 +1,22 @@
|
||||
import json
|
||||
|
||||
struct Test {
|
||||
optional_string ?string
|
||||
optional_array ?[]string
|
||||
optional_struct_array ?[]string
|
||||
optional_map ?map[string]string
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
test := Test{}
|
||||
encoded := json.encode(test)
|
||||
assert dump(encoded) == '{}'
|
||||
|
||||
test2 := Test{
|
||||
optional_map: {
|
||||
'foo': 'bar'
|
||||
}
|
||||
}
|
||||
encoded2 := json.encode(test2)
|
||||
assert dump(encoded2) == '{"optional_map":{"foo":"bar"}}'
|
||||
}
|
@ -135,8 +135,8 @@ ${enc_fn_dec} {
|
||||
m := sym.info as ast.Map
|
||||
g.gen_json_for_type(m.key_type)
|
||||
g.gen_json_for_type(m.value_type)
|
||||
dec.writeln(g.decode_map(m.key_type, m.value_type, ret_styp))
|
||||
enc.writeln(g.encode_map(m.key_type, m.value_type))
|
||||
dec.writeln(g.decode_map(utyp, m.key_type, m.value_type, ret_styp))
|
||||
enc.writeln(g.encode_map(utyp, m.key_type, m.value_type))
|
||||
} else if sym.kind == .alias {
|
||||
a := sym.info as ast.Alias
|
||||
parent_typ := a.parent_type
|
||||
@ -155,8 +155,8 @@ ${enc_fn_dec} {
|
||||
m := psym.info as ast.Map
|
||||
g.gen_json_for_type(m.key_type)
|
||||
g.gen_json_for_type(m.value_type)
|
||||
dec.writeln(g.decode_map(m.key_type, m.value_type, ret_styp))
|
||||
enc.writeln(g.encode_map(m.key_type, m.value_type))
|
||||
dec.writeln(g.decode_map(utyp, m.key_type, m.value_type, ret_styp))
|
||||
enc.writeln(g.encode_map(utyp, m.key_type, m.value_type))
|
||||
} else {
|
||||
verror('json: ${sym.name} is not struct')
|
||||
}
|
||||
@ -184,7 +184,7 @@ ${enc_fn_dec} {
|
||||
dec.writeln('\t${result_name}_${ret_styp} ret;')
|
||||
dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));')
|
||||
if utyp.has_flag(.option) {
|
||||
dec.writeln('\t_option_ok(&res.data, &ret.data, sizeof(${g.base_type(utyp)}));')
|
||||
dec.writeln('\t_option_ok(&res.data, (${option_name}*)&ret.data, sizeof(${g.base_type(utyp)}));')
|
||||
}
|
||||
dec.writeln('\treturn ret;\n}')
|
||||
enc.writeln('\treturn o;\n}')
|
||||
@ -241,7 +241,7 @@ fn (mut g Gen) gen_enum_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc strin
|
||||
if is_option {
|
||||
base_typ := g.typ(utyp.clear_flag(.option))
|
||||
enc.writeln('\to = ${js_enc_name('u64')}(*val.data);')
|
||||
dec.writeln('\t_option_ok(&(${base_typ}[]){ ${js_dec_name('u64')}(root) }, &res, sizeof(${base_typ}));')
|
||||
dec.writeln('\t_option_ok(&(${base_typ}[]){ ${js_dec_name('u64')}(root) }, (${option_name}*)&res, sizeof(${base_typ}));')
|
||||
} else {
|
||||
dec.writeln('\tres = ${js_dec_name('u64')}(root);')
|
||||
enc.writeln('\to = ${js_enc_name('u64')}(val);')
|
||||
@ -280,7 +280,7 @@ fn (mut g Gen) gen_option_enc_dec(typ ast.Type, mut enc strings.Builder, mut dec
|
||||
enc.writeln('\to = ${encode_name}(*(${type_str}*)val.data);')
|
||||
|
||||
dec_name := js_dec_name(type_str)
|
||||
dec.writeln('\t_option_ok(&(${type_str}[]){ ${dec_name}(root) }, &res, sizeof(${type_str}));')
|
||||
dec.writeln('\t_option_ok(&(${type_str}[]){ ${dec_name}(root) }, (${option_name}*)&res, sizeof(${type_str}));')
|
||||
}
|
||||
|
||||
[inline]
|
||||
@ -393,7 +393,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
||||
dec.writeln('\t\t${variant_typ} value = *(${variant_typ}*)(${tmp}.data);')
|
||||
}
|
||||
if is_option {
|
||||
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${variant_typ}_to_sumtype_${sym.cname}(&value) }, &res, sizeof(${sym.cname}));')
|
||||
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${variant_typ}_to_sumtype_${sym.cname}(&value) }, (${option_name}*)&res, sizeof(${sym.cname}));')
|
||||
} else {
|
||||
dec.writeln('\t\tres = ${variant_typ}_to_sumtype_${ret_styp}(&value);')
|
||||
}
|
||||
@ -806,7 +806,7 @@ fn (mut g Gen) decode_array(utyp ast.Type, value_type ast.Type, fixed_array_size
|
||||
fixed_array_idx_increment += 'fixed_array_idx++;'
|
||||
} else {
|
||||
array_element_assign += 'array_push${noscan}((array*)&res.data, &val);'
|
||||
res_str += '_option_ok(&(${g.base_type(utyp)}[]) { __new_array${noscan}(0, 0, sizeof(${styp})) }, &res, sizeof(${g.base_type(utyp)}));'
|
||||
res_str += '_option_ok(&(${g.base_type(utyp)}[]) { __new_array${noscan}(0, 0, sizeof(${styp})) }, (${option_name}*)&res, sizeof(${g.base_type(utyp)}));'
|
||||
array_free_str += 'array_free(&res.data);'
|
||||
}
|
||||
} else {
|
||||
@ -882,7 +882,7 @@ fn (mut g Gen) encode_array(utyp ast.Type, value_type ast.Type, fixed_array_size
|
||||
'
|
||||
}
|
||||
|
||||
fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type, ustyp string) string {
|
||||
fn (mut g Gen) decode_map(utyp ast.Type, key_type ast.Type, value_type ast.Type, ustyp string) string {
|
||||
styp := g.typ(key_type)
|
||||
mut styp_v := g.typ(value_type)
|
||||
ret_styp := styp_v.replace('*', '_ptr')
|
||||
@ -902,6 +902,22 @@ fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type, ustyp string)
|
||||
${styp_v} val = *(${styp_v}*)val2.data;
|
||||
'
|
||||
}
|
||||
|
||||
if utyp.has_flag(.option) {
|
||||
return '
|
||||
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
|
||||
return (${result_name}_${ustyp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
|
||||
}
|
||||
_option_ok(&(${g.base_type(utyp)}[]) { new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn}) }, (${option_name}*)&res, sizeof(${g.base_type(utyp)}));
|
||||
cJSON *jsval = NULL;
|
||||
cJSON_ArrayForEach(jsval, root)
|
||||
{
|
||||
${s}
|
||||
string key = tos2((byteptr)jsval->string);
|
||||
map_set((map*)res.data, &key, &val);
|
||||
}
|
||||
'
|
||||
} else {
|
||||
return '
|
||||
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
|
||||
return (${result_name}_${ustyp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
|
||||
@ -915,9 +931,10 @@ fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type, ustyp string)
|
||||
map_set(&res, &key, &val);
|
||||
}
|
||||
'
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) encode_map(key_type ast.Type, value_type ast.Type) string {
|
||||
fn (mut g Gen) encode_map(utyp ast.Type, key_type ast.Type, value_type ast.Type) string {
|
||||
styp := g.typ(key_type)
|
||||
styp_v := g.typ(value_type)
|
||||
fn_name_v := js_enc_name(styp_v)
|
||||
@ -930,6 +947,17 @@ fn (mut g Gen) encode_map(key_type ast.Type, value_type ast.Type) string {
|
||||
// key += '${styp}_str((($styp*)${keys_tmp}.data)[i]);'
|
||||
verror('json: encode only maps with string keys')
|
||||
}
|
||||
if utyp.has_flag(.option) {
|
||||
return '
|
||||
o = cJSON_CreateObject();
|
||||
Array_${styp} ${keys_tmp} = map_keys((map*)val.data);
|
||||
for (int i = 0; i < ${keys_tmp}.len; ++i) {
|
||||
${key}
|
||||
cJSON_AddItemToObject(o, (char*) key.str, ${fn_name_v} ( *(${styp_v}*) map_get((map*)val.data, &key, &(${styp_v}[]) { ${zero} } ) ) );
|
||||
}
|
||||
array_free(&${keys_tmp});
|
||||
'
|
||||
} else {
|
||||
return '
|
||||
o = cJSON_CreateObject();
|
||||
Array_${styp} ${keys_tmp} = map_keys(&val);
|
||||
@ -939,4 +967,5 @@ fn (mut g Gen) encode_map(key_type ast.Type, value_type ast.Type) string {
|
||||
}
|
||||
array_free(&${keys_tmp});
|
||||
'
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user