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
|
m := sym.info as ast.Map
|
||||||
g.gen_json_for_type(m.key_type)
|
g.gen_json_for_type(m.key_type)
|
||||||
g.gen_json_for_type(m.value_type)
|
g.gen_json_for_type(m.value_type)
|
||||||
dec.writeln(g.decode_map(m.key_type, m.value_type, ret_styp))
|
dec.writeln(g.decode_map(utyp, m.key_type, m.value_type, ret_styp))
|
||||||
enc.writeln(g.encode_map(m.key_type, m.value_type))
|
enc.writeln(g.encode_map(utyp, m.key_type, m.value_type))
|
||||||
} else if sym.kind == .alias {
|
} else if sym.kind == .alias {
|
||||||
a := sym.info as ast.Alias
|
a := sym.info as ast.Alias
|
||||||
parent_typ := a.parent_type
|
parent_typ := a.parent_type
|
||||||
@ -155,8 +155,8 @@ ${enc_fn_dec} {
|
|||||||
m := psym.info as ast.Map
|
m := psym.info as ast.Map
|
||||||
g.gen_json_for_type(m.key_type)
|
g.gen_json_for_type(m.key_type)
|
||||||
g.gen_json_for_type(m.value_type)
|
g.gen_json_for_type(m.value_type)
|
||||||
dec.writeln(g.decode_map(m.key_type, m.value_type, ret_styp))
|
dec.writeln(g.decode_map(utyp, m.key_type, m.value_type, ret_styp))
|
||||||
enc.writeln(g.encode_map(m.key_type, m.value_type))
|
enc.writeln(g.encode_map(utyp, m.key_type, m.value_type))
|
||||||
} else {
|
} else {
|
||||||
verror('json: ${sym.name} is not struct')
|
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_name}_${ret_styp} ret;')
|
||||||
dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));')
|
dec.writeln('\t_result_ok(&res, (${result_name}*)&ret, sizeof(res));')
|
||||||
if utyp.has_flag(.option) {
|
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}')
|
dec.writeln('\treturn ret;\n}')
|
||||||
enc.writeln('\treturn o;\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 {
|
if is_option {
|
||||||
base_typ := g.typ(utyp.clear_flag(.option))
|
base_typ := g.typ(utyp.clear_flag(.option))
|
||||||
enc.writeln('\to = ${js_enc_name('u64')}(*val.data);')
|
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 {
|
} else {
|
||||||
dec.writeln('\tres = ${js_dec_name('u64')}(root);')
|
dec.writeln('\tres = ${js_dec_name('u64')}(root);')
|
||||||
enc.writeln('\to = ${js_enc_name('u64')}(val);')
|
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);')
|
enc.writeln('\to = ${encode_name}(*(${type_str}*)val.data);')
|
||||||
|
|
||||||
dec_name := js_dec_name(type_str)
|
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]
|
[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);')
|
dec.writeln('\t\t${variant_typ} value = *(${variant_typ}*)(${tmp}.data);')
|
||||||
}
|
}
|
||||||
if is_option {
|
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 {
|
} else {
|
||||||
dec.writeln('\t\tres = ${variant_typ}_to_sumtype_${ret_styp}(&value);')
|
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++;'
|
fixed_array_idx_increment += 'fixed_array_idx++;'
|
||||||
} else {
|
} else {
|
||||||
array_element_assign += 'array_push${noscan}((array*)&res.data, &val);'
|
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);'
|
array_free_str += 'array_free(&res.data);'
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
styp := g.typ(key_type)
|
||||||
mut styp_v := g.typ(value_type)
|
mut styp_v := g.typ(value_type)
|
||||||
ret_styp := styp_v.replace('*', '_ptr')
|
ret_styp := styp_v.replace('*', '_ptr')
|
||||||
@ -902,22 +902,39 @@ fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type, ustyp string)
|
|||||||
${styp_v} val = *(${styp_v}*)val2.data;
|
${styp_v} val = *(${styp_v}*)val2.data;
|
||||||
'
|
'
|
||||||
}
|
}
|
||||||
return '
|
|
||||||
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
|
if utyp.has_flag(.option) {
|
||||||
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}};
|
return '
|
||||||
}
|
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
|
||||||
res = new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn});
|
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}};
|
||||||
cJSON *jsval = NULL;
|
}
|
||||||
cJSON_ArrayForEach(jsval, root)
|
_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;
|
||||||
${s}
|
cJSON_ArrayForEach(jsval, root)
|
||||||
string key = tos2((byteptr)jsval->string);
|
{
|
||||||
map_set(&res, &key, &val);
|
${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}};
|
||||||
|
}
|
||||||
|
res = new_map(sizeof(${styp}), sizeof(${styp_v}), ${hash_fn}, ${key_eq_fn}, ${clone_fn}, ${free_fn});
|
||||||
|
cJSON *jsval = NULL;
|
||||||
|
cJSON_ArrayForEach(jsval, root)
|
||||||
|
{
|
||||||
|
${s}
|
||||||
|
string key = tos2((byteptr)jsval->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 := g.typ(key_type)
|
||||||
styp_v := g.typ(value_type)
|
styp_v := g.typ(value_type)
|
||||||
fn_name_v := js_enc_name(styp_v)
|
fn_name_v := js_enc_name(styp_v)
|
||||||
@ -930,13 +947,25 @@ fn (mut g Gen) encode_map(key_type ast.Type, value_type ast.Type) string {
|
|||||||
// key += '${styp}_str((($styp*)${keys_tmp}.data)[i]);'
|
// key += '${styp}_str((($styp*)${keys_tmp}.data)[i]);'
|
||||||
verror('json: encode only maps with string keys')
|
verror('json: encode only maps with string keys')
|
||||||
}
|
}
|
||||||
return '
|
if utyp.has_flag(.option) {
|
||||||
o = cJSON_CreateObject();
|
return '
|
||||||
Array_${styp} ${keys_tmp} = map_keys(&val);
|
o = cJSON_CreateObject();
|
||||||
for (int i = 0; i < ${keys_tmp}.len; ++i) {
|
Array_${styp} ${keys_tmp} = map_keys((map*)val.data);
|
||||||
${key}
|
for (int i = 0; i < ${keys_tmp}.len; ++i) {
|
||||||
cJSON_AddItemToObject(o, (char*) key.str, ${fn_name_v} ( *(${styp_v}*) map_get(&val, &key, &(${styp_v}[]) { ${zero} } ) ) );
|
${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});
|
}
|
||||||
|
array_free(&${keys_tmp});
|
||||||
'
|
'
|
||||||
|
} else {
|
||||||
|
return '
|
||||||
|
o = cJSON_CreateObject();
|
||||||
|
Array_${styp} ${keys_tmp} = map_keys(&val);
|
||||||
|
for (int i = 0; i < ${keys_tmp}.len; ++i) {
|
||||||
|
${key}
|
||||||
|
cJSON_AddItemToObject(o, (char*) key.str, ${fn_name_v} ( *(${styp_v}*) map_get(&val, &key, &(${styp_v}[]) { ${zero} } ) ) );
|
||||||
|
}
|
||||||
|
array_free(&${keys_tmp});
|
||||||
|
'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user