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
|
assert y.age == 28
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct User {
|
||||||
|
age int
|
||||||
|
nums []int
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct User {
|
struct User {
|
||||||
age int
|
age int
|
||||||
@ -24,12 +29,15 @@ struct User {
|
|||||||
is_registered bool [json:IsRegistered]
|
is_registered bool [json:IsRegistered]
|
||||||
typ int [json:'type']
|
typ int [json:'type']
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn test_parse_user() {
|
fn test_parse_user() {
|
||||||
s := '{"age": 10, "nums": [1,2,3], "type": 0, "lastName": "Johnson", "IsRegistered": true}'
|
s := '{"age": 10, "nums": [1,2,3], "type": 0, "lastName": "Johnson", "IsRegistered": true}'
|
||||||
u := json.decode(User, s) or {
|
u := json.decode(User, s) or {
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
println(u)
|
||||||
|
/*
|
||||||
assert u.age == 10
|
assert u.age == 10
|
||||||
assert u.last_name == 'Johnson'
|
assert u.last_name == 'Johnson'
|
||||||
assert u.is_registered == true
|
assert u.is_registered == true
|
||||||
@ -38,8 +46,10 @@ fn test_parse_user() {
|
|||||||
assert u.nums[1] == 2
|
assert u.nums[1] == 2
|
||||||
assert u.nums[2] == 3
|
assert u.nums[2] == 3
|
||||||
assert u.typ == 0
|
assert u.typ == 0
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
fn test_encode_user(){
|
fn test_encode_user(){
|
||||||
usr := User{ age: 10, nums: [1,2,3], last_name: 'Johnson', is_registered: true, typ: 0}
|
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}'
|
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()`
|
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
||||||
array_fn_definitions []string // array equality functions that have been defined
|
array_fn_definitions []string // array equality functions that have been defined
|
||||||
is_json_fn bool // inside json.encode()
|
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
|
pcs []ProfileCounterMeta // -prof profile counter fn_names => fn counter name
|
||||||
attr string
|
attr string
|
||||||
is_builtin_mod bool
|
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 {
|
} else if node.expr_types[i] == table.bool_type {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(' ? _SLIT("true") : _SLIT("false")')
|
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`] {
|
if node.expr_types[i].is_signed() && specs[i] in [`x`, `X`, `o`] {
|
||||||
// convert to unsigned first befors C's integer propagation strikes
|
// convert to unsigned first befors C's integer propagation strikes
|
||||||
if node.expr_types[i] == table.i8_type {
|
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:
|
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||||
cctype := g.cc_type(st)
|
cctype := g.cc_type(st)
|
||||||
// Speaker_Cat_index = 0
|
// Speaker_Cat_index = 0
|
||||||
|
|
||||||
interface_index_name := '_${interface_name}_${cctype}_index'
|
interface_index_name := '_${interface_name}_${cctype}_index'
|
||||||
cast_functions.writeln('
|
cast_functions.writeln('
|
||||||
_Interface I_${cctype}_to_Interface_${interface_name}(${cctype}* x) {
|
_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)
|
// `json.decode(User, s)` => json.decode_User(s)
|
||||||
sym := g.table.get_type_symbol(ast_type.typ)
|
sym := g.table.get_type_symbol(ast_type.typ)
|
||||||
name += '_' + sym.name
|
name += '_' + sym.name
|
||||||
|
g.gen_json_for_type(ast_type.typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node.is_c {
|
if node.is_c {
|
||||||
|
@ -26,9 +26,13 @@ fn (mut g Gen) gen_json_for_type(typ table.Type) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sym.kind == .array {
|
if sym.kind == .array {
|
||||||
|
// return
|
||||||
|
}
|
||||||
|
if sym.name in g.json_types {
|
||||||
return
|
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
|
// decode_TYPE funcs receive an actual cJSON* object to decode
|
||||||
// cJSON_Parse(str) call is added by the compiler
|
// cJSON_Parse(str) call is added by the compiler
|
||||||
// Code gen decoder
|
// Code gen decoder
|
||||||
@ -52,37 +56,41 @@ Option ${dec_fn_name}(cJSON* root) {
|
|||||||
enc.writeln('
|
enc.writeln('
|
||||||
cJSON* ${enc_fn_name}($styp val) {
|
cJSON* ${enc_fn_name}($styp val) {
|
||||||
\tcJSON *o = cJSON_CreateObject();')
|
\tcJSON *o = cJSON_CreateObject();')
|
||||||
// Handle arrays
|
|
||||||
if sym.kind == .array {
|
if sym.kind == .array {
|
||||||
// dec += p.decode_array(t)
|
// Handle arrays
|
||||||
// enc += p.encode_array(t)
|
value_type := g.table.value_type(typ)
|
||||||
}
|
g.gen_json_for_type(value_type)
|
||||||
// Range through fields
|
dec.writeln(g.decode_array(value_type))
|
||||||
if !(sym.info is table.Struct) {
|
// enc += g.encode_array(t)
|
||||||
verror('json: $sym.name is not struct')
|
} else {
|
||||||
}
|
// Structs. Range through fields
|
||||||
info := sym.info as table.Struct
|
if !(sym.info is table.Struct) {
|
||||||
for field in info.fields {
|
verror('json: $sym.name is not struct')
|
||||||
if field.attr == 'skip' {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
name := if field.attr.starts_with('json:') { field.attr[5..] } else { field.name }
|
info := sym.info as table.Struct
|
||||||
field_type := g.typ(field.typ)
|
for field in info.fields {
|
||||||
enc_name := js_enc_name(field_type)
|
if field.attr == 'skip' {
|
||||||
if field.attr == 'raw' {
|
continue
|
||||||
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));')
|
|
||||||
}
|
}
|
||||||
|
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
|
// cJSON_delete
|
||||||
// p.cgen.fns << '$dec return opt_ok(res); \n}'
|
// 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' ||
|
return typ == 'int' || typ == 'string' || typ == 'bool' || typ == 'f32' || typ == 'f64' ||
|
||||||
typ == 'i8' || typ == 'i16' || typ == 'i64' || typ == 'u16' || typ == 'u32' || typ == 'u64'
|
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