json: decode/encode time.Time

pull/7467/head
Alexander Medvednikov 2020-12-22 07:24:41 +01:00
parent 9eb6c4ef87
commit b3e0926601
4 changed files with 69 additions and 26 deletions

View File

@ -1,4 +1,5 @@
import json import json
import time
enum JobTitle { enum JobTitle {
manager manager
@ -30,12 +31,14 @@ fn test_simple() {
} }
fn bar<T>(payload string) ?Bar { // ?T doesn't work currently fn bar<T>(payload string) ?Bar { // ?T doesn't work currently
result := json.decode(T, payload)? result := json.decode(T, payload) ?
return result return result
} }
struct Bar { struct Bar {
x string x string
} }
fn test_generic() { fn test_generic() {
result := bar<Bar>('{"x":"test"}') or { Bar{} } result := bar<Bar>('{"x":"test"}') or { Bar{} }
assert result.x == 'test' assert result.x == 'test'
@ -44,6 +47,7 @@ fn test_generic() {
struct User2 { struct User2 {
age int age int
nums []int nums []int
reg_date time.Time
} }
struct User { struct User {
@ -57,13 +61,9 @@ struct User {
fn test_parse_user() { fn test_parse_user() {
s := '{"age": 10, "nums": [1,2,3], "type": 1, "lastName": "Johnson", "IsRegistered": true, "pet_animals": {"name": "Bob", "animal": "Dog"}}' s := '{"age": 10, "nums": [1,2,3], "type": 1, "lastName": "Johnson", "IsRegistered": true, "pet_animals": {"name": "Bob", "animal": "Dog"}}'
u2 := json.decode(User2, s) or { u2 := json.decode(User2, s) or { exit(1) }
exit(1)
}
println(u2) println(u2)
u := json.decode(User, s) or { u := json.decode(User, s) or { exit(1) }
exit(1)
}
println(u) println(u)
assert u.age == 10 assert u.age == 10
assert u.last_name == 'Johnson' assert u.last_name == 'Johnson'
@ -76,6 +76,23 @@ fn test_parse_user() {
assert u.pets == '{"name":"Bob","animal":"Dog"}' assert u.pets == '{"name":"Bob","animal":"Dog"}'
} }
fn test_encode_decode_time() {
user := User2{
age: 25
reg_date: time.new_time(year: 2020, month: 12, day: 22, hour: 7, minute: 23)
}
s := json.encode(user)
println(s)
assert s.contains('"reg_date":1608621780')
user2 := json.decode(User2, s) or {
assert false
return
}
assert user2.reg_date.str() == '2020-12-22 07:23:00'
println(user2)
println(user2.reg_date)
}
fn (mut u User) foo() string { fn (mut u User) foo() string {
return json.encode(u) return json.encode(u)
} }
@ -258,7 +275,7 @@ fn test_nested_type() {
} }
} }
struct Foo<T> { struct Foo <T> {
pub: pub:
name string name string
data T data T
@ -268,9 +285,7 @@ fn test_generic_struct() {
foo_int := Foo<int>{'bar', 12} foo_int := Foo<int>{'bar', 12}
foo_enc := json.encode(foo_int) foo_enc := json.encode(foo_int)
assert foo_enc == '{"name":"bar","data":12}' assert foo_enc == '{"name":"bar","data":12}'
foo_dec := json.decode(Foo<int>, foo_enc) or { foo_dec := json.decode(Foo<int>, foo_enc) or { exit(1) }
exit(1)
}
assert foo_dec.name == 'bar' assert foo_dec.name == 'bar'
assert foo_dec.data == 12 assert foo_dec.data == 12
} }
@ -331,7 +346,7 @@ fn test_list() {
return return
} }
assert list.id == 1 assert list.id == 1
assert list.items == ["1", "2"] assert list.items == ['1', '2']
} }
fn test_list_no_id() { fn test_list_no_id() {
@ -340,7 +355,7 @@ fn test_list_no_id() {
return return
} }
assert list.id == 0 assert list.id == 0
assert list.items == ["1", "2"] assert list.items == ['1', '2']
} }
fn test_list_no_items() { fn test_list_no_items() {

View File

@ -6,6 +6,7 @@ module big
#include "bn.h" #include "bn.h"
[typedef] [typedef]
struct C.bn { struct C.bn {
mut:
array [32]u32 array [32]u32
} }
@ -105,6 +106,18 @@ pub fn from_string(input string) Number {
return n return n
} }
pub fn from_string2(input string) Number {
mut n := Number{}
C.bignum_init(&n)
if input.len == 0 {
return from_int(0)
}
for i, c in input {
n.array[i] = u32(c - `0`)
}
return n
}
pub fn (n Number) int() int { pub fn (n Number) int() int {
r := C.bignum_to_int(&n) r := C.bignum_to_int(&n)
return r return r

View File

@ -78,6 +78,10 @@ fn test_mod() {
} }
fn test_from_str() { fn test_from_str() {
x := big.from_string2('23')
println('kek')
println(x.str())
exit(0)
assert big.from_string('').hexstr() == '0' assert big.from_string('').hexstr() == '0'
assert big.from_string('1').hexstr() == '1' assert big.from_string('1').hexstr() == '1'
assert big.from_string('0').hexstr() == '0' assert big.from_string('0').hexstr() == '0'

View File

@ -126,6 +126,7 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
} }
field_type := g.typ(field.typ) field_type := g.typ(field.typ)
field_sym := g.table.get_type_symbol(field.typ) field_sym := g.table.get_type_symbol(field.typ)
// First generate decoding
if field.attrs.contains('raw') { if field.attrs.contains('raw') {
dec.writeln('\tres.${c_name(field.name)} = tos4(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));') dec.writeln('\tres.${c_name(field.name)} = tos4(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));')
} else { } else {
@ -137,6 +138,10 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
dec.writeln('\tres.${c_name(field.name)} = $dec_name (js_get(root, "$name"));') dec.writeln('\tres.${c_name(field.name)} = $dec_name (js_get(root, "$name"));')
} else if field_sym.kind == .enum_ { } else if field_sym.kind == .enum_ {
dec.writeln('\tres.${c_name(field.name)} = json__decode_u64(js_get(root, "$name"));') dec.writeln('\tres.${c_name(field.name)} = json__decode_u64(js_get(root, "$name"));')
} else if field_sym.name == 'time.Time' {
// time struct requires special treatment
// it has to be decoded from a unix timestamp number
dec.writeln('\tres.${c_name(field.name)} = time__unix(json__decode_u64(js_get(root, "$name")));')
} else if field_sym.kind == .alias { } else if field_sym.kind == .alias {
alias := field_sym.info as table.Alias alias := field_sym.info as table.Alias
parent_type := g.typ(alias.parent_type) parent_type := g.typ(alias.parent_type)
@ -162,6 +167,7 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
dec.writeln('\tres.${c_name(field.name)} = *($field_type*) ${tmp}.data;') dec.writeln('\tres.${c_name(field.name)} = *($field_type*) ${tmp}.data;')
} }
} }
// Encoding
mut enc_name := js_enc_name(field_type) mut enc_name := js_enc_name(field_type)
if !is_js_prim(field_type) { if !is_js_prim(field_type) {
if field_sym.kind == .alias { if field_sym.kind == .alias {
@ -171,10 +177,16 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
} }
if field_sym.kind == .enum_ { if field_sym.kind == .enum_ {
enc.writeln('\tcJSON_AddItemToObject(o, "$name", json__encode_u64(val.${c_name(field.name)}));') enc.writeln('\tcJSON_AddItemToObject(o, "$name", json__encode_u64(val.${c_name(field.name)}));')
} else {
if field_sym.name == 'time.Time' {
// time struct requires special treatment
// it has to be encoded as a unix timestamp number
enc.writeln('\tcJSON_AddItemToObject(o, "$name", json__encode_u64(val.${c_name(field.name)}.v_unix));')
} else { } else {
enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.${c_name(field.name)}));') enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.${c_name(field.name)}));')
} }
} }
}
} }
fn js_enc_name(typ string) string { fn js_enc_name(typ string) string {
@ -189,9 +201,8 @@ fn js_dec_name(typ string) string {
} }
fn is_js_prim(typ string) bool { fn is_js_prim(typ string) bool {
return typ == 'int' || typ == 'string' || typ == 'bool' || typ == 'f32' || typ == 'f64' || return typ in
typ == 'i8' || typ == 'i16' || typ == 'i64' || typ == 'u16' || typ == 'u32' || typ == 'u64' || ['int', 'string', 'bool', 'f32', 'f64', 'i8', 'i16', 'i64', 'u16', 'u32', 'u64', 'byte']
typ == 'byte'
} }
fn (mut g Gen) decode_array(value_type table.Type) string { fn (mut g Gen) decode_array(value_type table.Type) string {