mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
json: decode arrays
This commit is contained in:
parent
869444cec6
commit
ef6c418eb6
@ -16,6 +16,11 @@ fn test_simple() {
|
||||
assert y.age == 28
|
||||
}
|
||||
|
||||
struct User {
|
||||
age int
|
||||
nums []int
|
||||
}
|
||||
|
||||
/*
|
||||
struct User {
|
||||
age int
|
||||
@ -24,12 +29,15 @@ struct User {
|
||||
is_registered bool [json:IsRegistered]
|
||||
typ int [json:'type']
|
||||
}
|
||||
*/
|
||||
|
||||
fn test_parse_user() {
|
||||
s := '{"age": 10, "nums": [1,2,3], "type": 0, "lastName": "Johnson", "IsRegistered": true}'
|
||||
u := json.decode(User, s) or {
|
||||
exit(1)
|
||||
}
|
||||
println(u)
|
||||
/*
|
||||
assert u.age == 10
|
||||
assert u.last_name == 'Johnson'
|
||||
assert u.is_registered == true
|
||||
@ -38,8 +46,10 @@ fn test_parse_user() {
|
||||
assert u.nums[1] == 2
|
||||
assert u.nums[2] == 3
|
||||
assert u.typ == 0
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
fn test_encode_user(){
|
||||
usr := User{ age: 10, nums: [1,2,3], last_name: 'Johnson', is_registered: true, typ: 0}
|
||||
expected := '{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0}'
|
||||
|
@ -89,6 +89,7 @@ mut:
|
||||
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
||||
array_fn_definitions []string // array equality functions that have been defined
|
||||
is_json_fn bool // inside json.encode()
|
||||
json_types []string // to avoid json gen duplicates
|
||||
pcs []ProfileCounterMeta // -prof profile counter fn_names => fn counter name
|
||||
attr string
|
||||
is_builtin_mod bool
|
||||
@ -2470,7 +2471,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||
} else if node.expr_types[i] == table.bool_type {
|
||||
g.expr(expr)
|
||||
g.write(' ? _SLIT("true") : _SLIT("false")')
|
||||
} else if node.expr_types[i].is_number() || node.expr_types[i].is_pointer() || specs[i] == `d` {
|
||||
} else if node.expr_types[i].is_number() || node.expr_types[i].is_pointer() || specs[i] ==
|
||||
`d` {
|
||||
if node.expr_types[i].is_signed() && specs[i] in [`x`, `X`, `o`] {
|
||||
// convert to unsigned first befors C's integer propagation strikes
|
||||
if node.expr_types[i] == table.i8_type {
|
||||
@ -3445,7 +3447,6 @@ fn (g &Gen) interface_table() string {
|
||||
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||
cctype := g.cc_type(st)
|
||||
// Speaker_Cat_index = 0
|
||||
|
||||
interface_index_name := '_${interface_name}_${cctype}_index'
|
||||
cast_functions.writeln('
|
||||
_Interface I_${cctype}_to_Interface_${interface_name}(${cctype}* x) {
|
||||
|
@ -399,6 +399,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||
// `json.decode(User, s)` => json.decode_User(s)
|
||||
sym := g.table.get_type_symbol(ast_type.typ)
|
||||
name += '_' + sym.name
|
||||
g.gen_json_for_type(ast_type.typ)
|
||||
}
|
||||
}
|
||||
if node.is_c {
|
||||
|
@ -26,9 +26,13 @@ fn (mut g Gen) gen_json_for_type(typ table.Type) {
|
||||
return
|
||||
}
|
||||
if sym.kind == .array {
|
||||
// return
|
||||
}
|
||||
if sym.name in g.json_types {
|
||||
return
|
||||
}
|
||||
// println('gen_json_for_type($typ.name)')
|
||||
g.json_types << sym.name
|
||||
// println('gen_json_for_type($sym.name)')
|
||||
// decode_TYPE funcs receive an actual cJSON* object to decode
|
||||
// cJSON_Parse(str) call is added by the compiler
|
||||
// Code gen decoder
|
||||
@ -52,37 +56,41 @@ Option ${dec_fn_name}(cJSON* root) {
|
||||
enc.writeln('
|
||||
cJSON* ${enc_fn_name}($styp val) {
|
||||
\tcJSON *o = cJSON_CreateObject();')
|
||||
// Handle arrays
|
||||
if sym.kind == .array {
|
||||
// dec += p.decode_array(t)
|
||||
// enc += p.encode_array(t)
|
||||
}
|
||||
// Range through fields
|
||||
if !(sym.info is table.Struct) {
|
||||
verror('json: $sym.name is not struct')
|
||||
}
|
||||
info := sym.info as table.Struct
|
||||
for field in info.fields {
|
||||
if field.attr == 'skip' {
|
||||
continue
|
||||
// Handle arrays
|
||||
value_type := g.table.value_type(typ)
|
||||
g.gen_json_for_type(value_type)
|
||||
dec.writeln(g.decode_array(value_type))
|
||||
// enc += g.encode_array(t)
|
||||
} else {
|
||||
// Structs. Range through fields
|
||||
if !(sym.info is table.Struct) {
|
||||
verror('json: $sym.name is not struct')
|
||||
}
|
||||
name := if field.attr.starts_with('json:') { field.attr[5..] } else { field.name }
|
||||
field_type := g.typ(field.typ)
|
||||
enc_name := js_enc_name(field_type)
|
||||
if field.attr == 'raw' {
|
||||
dec.writeln(' res->$field.name = tos2(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));')
|
||||
} else {
|
||||
// Now generate decoders for all field types in this struct
|
||||
// need to do it here so that these functions are generated first
|
||||
g.gen_json_for_type(field.typ)
|
||||
dec_name := js_dec_name(field_type)
|
||||
if is_js_prim(field_type) {
|
||||
dec.writeln(' res . $field.name = $dec_name (js_get(' + 'root, "$name"));')
|
||||
} else {
|
||||
dec.writeln(' $dec_name (js_get(root, "$name"), & (res . $field.name));')
|
||||
info := sym.info as table.Struct
|
||||
for field in info.fields {
|
||||
if field.attr == 'skip' {
|
||||
continue
|
||||
}
|
||||
name := if field.attr.starts_with('json:') { field.attr[5..] } else { field.name }
|
||||
field_type := g.typ(field.typ)
|
||||
enc_name := js_enc_name(field_type)
|
||||
if field.attr == 'raw' {
|
||||
dec.writeln(' res->$field.name = tos2(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));')
|
||||
} else {
|
||||
// Now generate decoders for all field types in this struct
|
||||
// need to do it here so that these functions are generated first
|
||||
g.gen_json_for_type(field.typ)
|
||||
dec_name := js_dec_name(field_type)
|
||||
if is_js_prim(field_type) {
|
||||
dec.writeln(' res . $field.name = $dec_name (js_get(root, "$name"));')
|
||||
} else {
|
||||
// dec.writeln(' $dec_name (js_get(root, "$name"), & (res . $field.name));')
|
||||
dec.writeln(' res . $field.name = *($field_type*) $dec_name (js_get(root,"$name")).data;')
|
||||
}
|
||||
}
|
||||
enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.$field.name));')
|
||||
}
|
||||
enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.$field.name));')
|
||||
}
|
||||
// cJSON_delete
|
||||
// p.cgen.fns << '$dec return opt_ok(res); \n}'
|
||||
@ -106,3 +114,25 @@ fn is_js_prim(typ string) bool {
|
||||
return typ == 'int' || typ == 'string' || typ == 'bool' || typ == 'f32' || typ == 'f64' ||
|
||||
typ == 'i8' || typ == 'i16' || typ == 'i64' || typ == 'u16' || typ == 'u32' || typ == 'u64'
|
||||
}
|
||||
|
||||
fn (mut g Gen) decode_array(value_type table.Type) string {
|
||||
styp := g.typ(value_type)
|
||||
fn_name := js_dec_name(styp)
|
||||
// If we have `[]Profile`, have to register a Profile en(de)coder first
|
||||
g.gen_json_for_type(value_type)
|
||||
mut s := ''
|
||||
if is_js_prim(styp) {
|
||||
s = '$styp val = ${fn_name}(jsval); '
|
||||
} else {
|
||||
s = '\t$styp val; ${fn_name}(jsval, &val); '
|
||||
}
|
||||
return '
|
||||
res = __new_array(0, 0, sizeof($styp));
|
||||
const cJSON *jsval = NULL;
|
||||
cJSON_ArrayForEach(jsval, root)
|
||||
{
|
||||
$s
|
||||
array_push(&res, &val);
|
||||
}
|
||||
'
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user