mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
json2: decode refactor/fix (#16588)
This commit is contained in:
parent
50110d4c19
commit
5288c613ef
@ -58,8 +58,8 @@ fn test_int() {
|
||||
assert sample_data['f32'] or { 0 }.int() == 2
|
||||
assert sample_data['f64'] or { 0 }.int() == 1
|
||||
assert json.Any(true).int() == 1
|
||||
assert json.Any('123').int() == 123
|
||||
// invalid conversions
|
||||
assert json.Any('123').int() == 0
|
||||
assert sample_data['null'] or { 0 }.int() == 0
|
||||
assert sample_data['arr'] or { 0 }.int() == 0
|
||||
assert sample_data['obj'] or { 0 }.int() == 0
|
||||
@ -72,8 +72,8 @@ fn test_i64() {
|
||||
assert sample_data['f32'] or { 0 }.i64() == 2
|
||||
assert sample_data['f64'] or { 0 }.i64() == 1
|
||||
assert json.Any(true).i64() == 1
|
||||
assert json.Any('123').i64() == 123
|
||||
// invalid conversions
|
||||
assert json.Any('123').i64() == 0
|
||||
assert sample_data['null'] or { 0 }.i64() == 0
|
||||
assert sample_data['arr'] or { 0 }.i64() == 0
|
||||
assert sample_data['obj'] or { 0 }.i64() == 0
|
||||
|
@ -59,7 +59,7 @@ pub fn (err UnknownTokenError) msg() string {
|
||||
}
|
||||
|
||||
struct Parser {
|
||||
mut:
|
||||
pub mut:
|
||||
scanner &Scanner = unsafe { nil }
|
||||
p_tok Token
|
||||
tok Token
|
||||
|
@ -1,48 +1,48 @@
|
||||
module json2
|
||||
import x.json2 as json
|
||||
|
||||
fn test_raw_decode_string() {
|
||||
str := raw_decode('"Hello!"')!
|
||||
str := json.raw_decode('"Hello!"')!
|
||||
assert str.str() == 'Hello!'
|
||||
}
|
||||
|
||||
fn test_raw_decode_string_escape() {
|
||||
jstr := raw_decode('"\u001b"')!
|
||||
jstr := json.raw_decode('"\u001b"')!
|
||||
str := jstr.str()
|
||||
assert str.len == 1
|
||||
assert str[0] == 27
|
||||
}
|
||||
|
||||
fn test_raw_decode_number() {
|
||||
num := raw_decode('123')!
|
||||
num := json.raw_decode('123')!
|
||||
assert num.int() == 123
|
||||
}
|
||||
|
||||
fn test_raw_decode_array() {
|
||||
raw_arr := raw_decode('["Foo", 1]')!
|
||||
raw_arr := json.raw_decode('["Foo", 1]')!
|
||||
arr := raw_arr.arr()
|
||||
assert arr[0] or { 0 }.str() == 'Foo'
|
||||
assert arr[1] or { 0 }.int() == 1
|
||||
}
|
||||
|
||||
fn test_raw_decode_bool() {
|
||||
bol := raw_decode('false')!
|
||||
bol := json.raw_decode('false')!
|
||||
assert bol.bool() == false
|
||||
}
|
||||
|
||||
fn test_raw_decode_map() {
|
||||
raw_mp := raw_decode('{"name":"Bob","age":20}')!
|
||||
raw_mp := json.raw_decode('{"name":"Bob","age":20}')!
|
||||
mp := raw_mp.as_map()
|
||||
assert mp['name'] or { 0 }.str() == 'Bob'
|
||||
assert mp['age'] or { 0 }.int() == 20
|
||||
}
|
||||
|
||||
fn test_raw_decode_null() {
|
||||
nul := raw_decode('null')!
|
||||
assert nul is Null
|
||||
nul := json.raw_decode('null')!
|
||||
assert nul is json.Null
|
||||
}
|
||||
|
||||
fn test_raw_decode_invalid() {
|
||||
raw_decode('1z') or {
|
||||
json.raw_decode('1z') or {
|
||||
assert err.msg() == '[x.json2] invalid token `z` (0:17)'
|
||||
return
|
||||
}
|
||||
@ -50,25 +50,25 @@ fn test_raw_decode_invalid() {
|
||||
}
|
||||
|
||||
fn test_raw_decode_string_with_dollarsign() {
|
||||
str := raw_decode(r'"Hello $world"')!
|
||||
str := json.raw_decode(r'"Hello $world"')!
|
||||
assert str.str() == r'Hello $world'
|
||||
}
|
||||
|
||||
fn test_raw_decode_map_with_whitespaces() {
|
||||
raw_mp := raw_decode(' \n\t{"name":"Bob","age":20}\n\t')!
|
||||
raw_mp := json.raw_decode(' \n\t{"name":"Bob","age":20}\n\t')!
|
||||
mp := raw_mp.as_map()
|
||||
assert mp['name'] or { 0 }.str() == 'Bob'
|
||||
assert mp['age'] or { 0 }.int() == 20
|
||||
}
|
||||
|
||||
fn test_nested_array_object() {
|
||||
mut parser := new_parser(r'[[[[[],[],[]]]],{"Test":{}},[[]]]', false)
|
||||
mut parser := json.new_parser(r'[[[[[],[],[]]]],{"Test":{}},[[]]]', false)
|
||||
decoded := parser.decode()!
|
||||
assert parser.n_level == 0
|
||||
}
|
||||
|
||||
fn test_raw_decode_map_invalid() {
|
||||
raw_decode('{"name","Bob","age":20}') or {
|
||||
json.raw_decode('{"name","Bob","age":20}') or {
|
||||
assert err.msg() == '[x.json2] invalid token `comma`, expecting `colon` (0:5)'
|
||||
return
|
||||
}
|
||||
@ -76,7 +76,7 @@ fn test_raw_decode_map_invalid() {
|
||||
}
|
||||
|
||||
fn test_raw_decode_array_invalid() {
|
||||
raw_decode('["Foo", 1,}') or {
|
||||
json.raw_decode('["Foo", 1,}') or {
|
||||
assert err.msg() == '[x.json2] invalid token `rcbr` (0:5)'
|
||||
return
|
||||
}
|
||||
|
@ -12,42 +12,11 @@ mut:
|
||||
sx64 i64
|
||||
}
|
||||
|
||||
pub fn (mut x IntegerValues) from_json(f json2.Any) {
|
||||
fm := f.as_map()
|
||||
if v := fm['ux8'] {
|
||||
x.ux8 = u8(v.u64())
|
||||
}
|
||||
if v := fm['ux16'] {
|
||||
x.ux16 = u16(v.u64())
|
||||
}
|
||||
if v := fm['ux32'] {
|
||||
x.ux32 = u32(v.u64())
|
||||
}
|
||||
if v := fm['ux64'] {
|
||||
x.ux64 = v.u64()
|
||||
}
|
||||
//
|
||||
if v := fm['sx8'] {
|
||||
x.sx8 = i8(v.i64())
|
||||
}
|
||||
if v := fm['sx16'] {
|
||||
x.sx16 = i16(v.i64())
|
||||
}
|
||||
if v := fm['sx32'] {
|
||||
x.sx32 = int(v.i64())
|
||||
}
|
||||
if v := fm['sx64'] {
|
||||
x.sx64 = v.i64()
|
||||
}
|
||||
}
|
||||
|
||||
fn test_all_primitive_integer_types_are_encodable_and_decodable() {
|
||||
f := IntegerValues{1, 2, 3, 4, -1, -2, -3, -4}
|
||||
s := json2.encode[IntegerValues](f)
|
||||
dump(s)
|
||||
assert s == '{"ux8":1,"ux16":2,"ux32":3,"ux64":4,"sx8":-1,"sx16":-2,"sx32":-3,"sx64":-4}'
|
||||
x := json2.decode[IntegerValues](s)!
|
||||
dump(x)
|
||||
assert x == f
|
||||
println('done')
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
module json2
|
||||
|
||||
import strings
|
||||
import time
|
||||
|
||||
// Decodes a JSON string into an `Any` type. Returns an option.
|
||||
pub fn raw_decode(src string) !Any {
|
||||
@ -19,9 +20,41 @@ pub fn fast_raw_decode(src string) !Any {
|
||||
|
||||
// decode is a generic function that decodes a JSON string into the target type.
|
||||
pub fn decode[T](src string) !T {
|
||||
res := raw_decode(src)!
|
||||
res := raw_decode(src)!.as_map()
|
||||
mut typ := T{}
|
||||
typ.from_json(res)
|
||||
$for field in T.fields {
|
||||
$if field.typ is u8 {
|
||||
typ.$(field.name) = u8(res[field.name]!.u64())
|
||||
} $else $if field.typ is u16 {
|
||||
typ.$(field.name) = u16(res[field.name]!.u64())
|
||||
} $else $if field.typ is u32 {
|
||||
typ.$(field.name) = u32(res[field.name]!.u64())
|
||||
} $else $if field.typ is u64 {
|
||||
typ.$(field.name) = res[field.name]!.u64()
|
||||
} $else $if field.typ is int {
|
||||
typ.$(field.name) = res[field.name]!.int()
|
||||
} $else $if field.typ is i8 {
|
||||
typ.$(field.name) = i8(res[field.name]!.i64())
|
||||
} $else $if field.typ is i16 {
|
||||
typ.$(field.name) = i16(res[field.name]!.i64())
|
||||
} $else $if field.typ is i32 {
|
||||
// typ.$(field.name) = res[field.name]!.i32()
|
||||
} $else $if field.typ is i64 {
|
||||
typ.$(field.name) = res[field.name]!.i64()
|
||||
} $else $if field.typ is f32 {
|
||||
typ.$(field.name) = res[field.name]!.f32()
|
||||
} $else $if field.typ is f64 {
|
||||
typ.$(field.name) = res[field.name]!.f64()
|
||||
} $else $if field.typ is bool {
|
||||
typ.$(field.name) = res[field.name]!.bool()
|
||||
} $else $if field.typ is string {
|
||||
typ.$(field.name) = res[field.name]!.str()
|
||||
} $else $if field.typ is time.Time {
|
||||
// typ.$(field.name) = res[field.name]!.str()
|
||||
} $else {
|
||||
return error("The type of `${field.name}` can't be decoded. Please open an issue at https://github.com/vlang/v/issues/new/choose")
|
||||
}
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
@ -41,57 +74,133 @@ pub fn encode[T](val T) string {
|
||||
// int uses `Any` as an integer.
|
||||
pub fn (f Any) int() int {
|
||||
match f {
|
||||
int { return f }
|
||||
i8, i16, i64, u8, u16, u32, u64, f32, f64, bool { return int(f) }
|
||||
else { return 0 }
|
||||
int {
|
||||
return f
|
||||
}
|
||||
i8, i16, i64, u8, u16, u32, u64, f32, f64, bool {
|
||||
return int(f)
|
||||
}
|
||||
string {
|
||||
if f == 'false' || f == 'true' {
|
||||
return int(f.bool())
|
||||
}
|
||||
return f.int()
|
||||
}
|
||||
else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// i64 uses `Any` as a 64-bit integer.
|
||||
pub fn (f Any) i64() i64 {
|
||||
match f {
|
||||
i64 { return f }
|
||||
i8, i16, int, u8, u16, u32, u64, f32, f64, bool { return i64(f) }
|
||||
else { return 0 }
|
||||
i64 {
|
||||
return f
|
||||
}
|
||||
i8, i16, int, u8, u16, u32, u64, f32, f64, bool {
|
||||
return i64(f)
|
||||
}
|
||||
string {
|
||||
if f == 'false' || f == 'true' {
|
||||
return i64(f.bool())
|
||||
}
|
||||
return f.i64()
|
||||
}
|
||||
else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// u64 uses `Any` as a 64-bit unsigned integer.
|
||||
pub fn (f Any) u64() u64 {
|
||||
match f {
|
||||
u64 { return f }
|
||||
u8, u16, u32, i8, i16, int, i64, f32, f64, bool { return u64(f) }
|
||||
else { return 0 }
|
||||
u64 {
|
||||
return f
|
||||
}
|
||||
u8, u16, u32, i8, i16, int, i64, f32, f64, bool {
|
||||
return u64(f)
|
||||
}
|
||||
string {
|
||||
if f == 'false' || f == 'true' {
|
||||
return u64(f.bool())
|
||||
}
|
||||
return f.u64()
|
||||
}
|
||||
else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// f32 uses `Any` as a 32-bit float.
|
||||
pub fn (f Any) f32() f32 {
|
||||
match f {
|
||||
f32 { return f }
|
||||
bool, i8, i16, int, i64, u8, u16, u32, u64, f64 { return f32(f) }
|
||||
else { return 0.0 }
|
||||
f32 {
|
||||
return f
|
||||
}
|
||||
bool, i8, i16, int, i64, u8, u16, u32, u64, f64 {
|
||||
return f32(f)
|
||||
}
|
||||
string {
|
||||
if f == 'false' || f == 'true' {
|
||||
return f32(f.bool())
|
||||
}
|
||||
return f.f32()
|
||||
}
|
||||
else {
|
||||
return 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// f64 uses `Any` as a 64-bit float.
|
||||
pub fn (f Any) f64() f64 {
|
||||
match f {
|
||||
f64 { return f }
|
||||
i8, i16, int, i64, u8, u16, u32, u64, f32 { return f64(f) }
|
||||
else { return 0.0 }
|
||||
f64 {
|
||||
return f
|
||||
}
|
||||
i8, i16, int, i64, u8, u16, u32, u64, f32 {
|
||||
return f64(f)
|
||||
}
|
||||
string {
|
||||
if f == 'false' || f == 'true' {
|
||||
return f64(f.bool())
|
||||
}
|
||||
return f.f64()
|
||||
}
|
||||
else {
|
||||
return 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bool uses `Any` as a bool.
|
||||
pub fn (f Any) bool() bool {
|
||||
match f {
|
||||
bool { return f }
|
||||
string { return f.bool() }
|
||||
i8, i16, int, i64 { return i64(f) != 0 }
|
||||
u8, u16, u32, u64 { return u64(f) != 0 }
|
||||
f32, f64 { return f64(f) != 0.0 }
|
||||
else { return false }
|
||||
bool {
|
||||
return f
|
||||
}
|
||||
string {
|
||||
if f.len > 0 {
|
||||
return f != '0' && f != '0.0' && f != 'false'
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
i8, i16, int, i64 {
|
||||
return i64(f) != 0
|
||||
}
|
||||
u8, u16, u32, u64 {
|
||||
return u64(f) != 0
|
||||
}
|
||||
f32, f64 {
|
||||
return f64(f) != 0.0
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,14 +44,6 @@ fn (e Employee) to_json() string {
|
||||
return mp.str()
|
||||
}
|
||||
|
||||
fn (mut e Employee) from_json(any json.Any) {
|
||||
mp := any.as_map()
|
||||
e.name = mp['name'] or { json.Any('') }.str()
|
||||
e.age = mp['age'] or { json.Any(0) }.int()
|
||||
e.salary = mp['salary'] or { json.Any(0) }.f32()
|
||||
e.title = unsafe { JobTitle(mp['title'] or { json.Any(0) }.int()) }
|
||||
}
|
||||
|
||||
// ! BUGFIX
|
||||
// fn test_simplegg() {
|
||||
// // x := EmployeeOp{'Peter', 28, 95000.5, .worker}
|
||||
@ -102,92 +94,34 @@ fn test_character_unescape() {
|
||||
assert lines['slash'] or { 0 }.str() == '/dev/null'
|
||||
}
|
||||
|
||||
fn (mut u User2) from_json(an json.Any) {
|
||||
mp := an.as_map()
|
||||
mut js_field_name := ''
|
||||
$for field in User.fields {
|
||||
js_field_name = field.name
|
||||
for attr in field.attrs {
|
||||
if attr.starts_with('json:') {
|
||||
js_field_name = attr.all_after('json:').trim_left(' ')
|
||||
break
|
||||
}
|
||||
}
|
||||
match field.name {
|
||||
'age' { u.age = mp[js_field_name] or { 0 }.int() }
|
||||
'nums' { u.nums = mp[js_field_name] or { 0 }.arr().map(it.int()) }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
struct MultTypeTest[T] {
|
||||
mut:
|
||||
val T
|
||||
}
|
||||
|
||||
struct User2 {
|
||||
pub mut:
|
||||
age int
|
||||
nums []int
|
||||
reg_date time.Time
|
||||
}
|
||||
// NOTE - This can substitute a lot of others tests
|
||||
fn test_bool_decode() {
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": ""}')!.val == false
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": "0"}')!.val == false
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": "1"}')!.val == true
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": "2"}')!.val == true
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": 0}')!.val == false
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": 1}')!.val == true
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": 2}')!.val == true
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": "true"}')!.val == true
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": "false"}')!.val == false
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": true}')!.val == true
|
||||
assert json.decode[MultTypeTest[bool]]('{"val": false}')!.val == false
|
||||
|
||||
struct User {
|
||||
pub mut:
|
||||
age int
|
||||
nums []int
|
||||
last_name string [json: lastName]
|
||||
is_registered bool [json: IsRegistered]
|
||||
typ int [json: 'type']
|
||||
pets string [json: 'pet_animals'; raw]
|
||||
}
|
||||
|
||||
fn (mut u User) from_json(an json.Any) {
|
||||
mp := an.as_map()
|
||||
mut js_field_name := ''
|
||||
$for field in User.fields {
|
||||
// FIXME: C error when initializing js_field_name inside comptime for
|
||||
js_field_name = field.name
|
||||
for attr in field.attrs {
|
||||
if attr.starts_with('json:') {
|
||||
js_field_name = attr.all_after('json:').trim_left(' ')
|
||||
break
|
||||
}
|
||||
}
|
||||
match field.name {
|
||||
'age' { u.age = mp[js_field_name] or { 0 }.int() }
|
||||
'nums' { u.nums = mp[js_field_name] or { 0 }.arr().map(it.int()) }
|
||||
'last_name' { u.last_name = mp[js_field_name] or { 0 }.str() }
|
||||
'is_registered' { u.is_registered = mp[js_field_name] or { 0 }.bool() }
|
||||
'typ' { u.typ = mp[js_field_name] or { 0 }.int() }
|
||||
'pets' { u.pets = mp[js_field_name] or { 0 }.str() }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (u User) to_json() string {
|
||||
// TODO: derive from field
|
||||
mut mp := {
|
||||
'age': json.Any(u.age)
|
||||
}
|
||||
mp['nums'] = u.nums.map(json.Any(it))
|
||||
mp['lastName'] = json.Any(u.last_name)
|
||||
mp['IsRegistered'] = json.Any(u.is_registered)
|
||||
mp['type'] = json.Any(u.typ)
|
||||
mp['pet_animals'] = json.Any(u.pets)
|
||||
return mp.str()
|
||||
}
|
||||
|
||||
struct Color {
|
||||
pub mut:
|
||||
space string
|
||||
point string [raw]
|
||||
}
|
||||
|
||||
fn (mut c Color) from_json(an json.Any) {
|
||||
mp := an.as_map()
|
||||
$for field in Color.fields {
|
||||
match field.name {
|
||||
'space' { c.space = mp[field.name] or { 0 }.str() }
|
||||
'point' { c.point = mp[field.name] or { 0 }.str() }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
assert json.decode[MultTypeTest[int]]('{"val": ""}')!.val == 0
|
||||
assert json.decode[MultTypeTest[int]]('{"val": "0"}')!.val == 0
|
||||
assert json.decode[MultTypeTest[int]]('{"val": "1"}')!.val == 1
|
||||
assert json.decode[MultTypeTest[int]]('{"val": "2"}')!.val == 2
|
||||
assert json.decode[MultTypeTest[int]]('{"val": 0}')!.val == 0
|
||||
assert json.decode[MultTypeTest[int]]('{"val": 1}')!.val == 1
|
||||
assert json.decode[MultTypeTest[int]]('{"val": 2}')!.val == 2
|
||||
assert json.decode[MultTypeTest[int]]('{"val": "true"}')!.val == 1
|
||||
assert json.decode[MultTypeTest[int]]('{"val": "false"}')!.val == 0
|
||||
assert json.decode[MultTypeTest[int]]('{"val": true}')!.val == 1
|
||||
assert json.decode[MultTypeTest[int]]('{"val": false}')!.val == 0
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ fn test_json_decode_with_optional_arg() {
|
||||
}
|
||||
|
||||
fn print_info() !string {
|
||||
dbconf := json.decode<DbConfig>(os.read_file('dbconf.json')!)!
|
||||
dbconf := json.decode[DbConfig](os.read_file('dbconf.json')!)!
|
||||
println(dbconf)
|
||||
return '${dbconf}'
|
||||
}
|
@ -7,15 +7,15 @@ struct Some {
|
||||
}
|
||||
|
||||
fn test_json_decode_with_sumtype() {
|
||||
v1 := json.decode<Some>('{"t": ["string", "string2"]}')!
|
||||
v1 := json.decode[Some]('{"t": ["string", "string2"]}')!
|
||||
println(v1)
|
||||
assert v1.t == Test(['string', 'string2'])
|
||||
|
||||
v2 := json.decode<Some>('{"t": [11, 22]}')!
|
||||
v2 := json.decode[Some]('{"t": [11, 22]}')!
|
||||
println(v2)
|
||||
assert v2.t == Test([11, 22])
|
||||
|
||||
v3 := json.decode<Some>('{"t": [true, false]}')!
|
||||
v3 := json.decode[Some]('{"t": [true, false]}')!
|
||||
println(v3)
|
||||
assert v3.t == Test([true, false])
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import x.json2 as json
|
||||
import time
|
||||
// import time
|
||||
|
||||
enum JobTitle {
|
||||
manager
|
||||
@ -9,11 +9,11 @@ enum JobTitle {
|
||||
|
||||
struct Employee {
|
||||
pub mut:
|
||||
name string
|
||||
age int
|
||||
salary f32
|
||||
title JobTitle
|
||||
sub_employee SubEmployee
|
||||
name string
|
||||
age int
|
||||
salary f32
|
||||
// title JobTitle //! FIXME - decode
|
||||
// sub_employee SubEmployee //! FIXME - decode
|
||||
}
|
||||
|
||||
struct SubEmployee {
|
||||
@ -21,37 +21,30 @@ pub mut:
|
||||
name string
|
||||
age int
|
||||
salary f32
|
||||
title JobTitle
|
||||
// title JobTitle //! FIXME - decode
|
||||
}
|
||||
|
||||
fn test_simple() {
|
||||
sub_employee := SubEmployee{
|
||||
name: 'João'
|
||||
}
|
||||
x := Employee{'Peter', 28, 95000.5, .worker, sub_employee}
|
||||
x := Employee{'Peter', 28, 95000.5}
|
||||
s := json.encode[Employee](x)
|
||||
assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":2,"sub_employee":{"name":"João","age":0,"salary":0.0,"title":0}}'
|
||||
// y := json.decode<Employee>(s) or {
|
||||
// println(err)
|
||||
// assert false
|
||||
// return
|
||||
// }
|
||||
// assert y.name == 'Peter'
|
||||
// assert y.age == 28
|
||||
// assert y.salary == 95000.5
|
||||
// assert y.title == .worker
|
||||
// x := Employee{'Peter', 28, 95000.5, .worker}
|
||||
// s := json.encode<Employee>(x)
|
||||
// assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":2}'
|
||||
// // y := json.decode<Employee>(s) or {
|
||||
// // println(err)
|
||||
// // assert false
|
||||
// // return
|
||||
// // }
|
||||
// // assert y.name == 'Peter'
|
||||
// // assert y.age == 28
|
||||
// // assert y.salary == 95000.5
|
||||
// // assert y.title == .worker
|
||||
assert s == '{"name":"Peter","age":28,"salary":95000.5}'
|
||||
|
||||
y := json.decode[Employee](s) or {
|
||||
println(err)
|
||||
assert false
|
||||
return
|
||||
}
|
||||
assert y.name == 'Peter'
|
||||
assert y.age == 28
|
||||
assert y.salary == 95000.5
|
||||
// assert y.title == .worker //! FIXME
|
||||
// assert y.sub_employee.name == 'Peter'
|
||||
// assert y.sub_employee.age == 0
|
||||
// assert y.sub_employee.salary == 0.0
|
||||
// assert y.sub_employee.title == .worker //! FIXME
|
||||
}
|
||||
|
||||
// const currency_id = 'cconst'
|
||||
@ -100,11 +93,11 @@ fn test_encode_user() {
|
||||
assert usr.foo() == expected
|
||||
}
|
||||
|
||||
// struct Color {
|
||||
// pub mut:
|
||||
// space string
|
||||
// point string [raw]
|
||||
// }
|
||||
struct Color {
|
||||
pub mut:
|
||||
space string
|
||||
point string [raw]
|
||||
}
|
||||
|
||||
fn test_encode_map() {
|
||||
expected := '{"one":1,"two":2,"three":3,"four":4}'
|
||||
@ -147,3 +140,41 @@ struct StByteArray {
|
||||
fn test_byte_array() {
|
||||
assert json.encode(StByteArray{ ba: [byte(1), 2, 3, 4, 5] }) == '{"ba":[1,2,3,4,5]}'
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
x string
|
||||
}
|
||||
|
||||
fn bar[T](payload string) !Bar { // ?T doesn't work currently
|
||||
result := json.decode[T](payload)!
|
||||
return result
|
||||
}
|
||||
|
||||
fn test_generic() {
|
||||
result := bar[Bar]('{"x":"test"}') or { Bar{} }
|
||||
assert result.x == 'test'
|
||||
}
|
||||
|
||||
fn test_raw_json_field() {
|
||||
color := json.decode[Color]('{"space": "YCbCr", "point": {"Y": 123}}') or {
|
||||
assert false
|
||||
Color{}
|
||||
}
|
||||
assert color.point == '{"Y":123}'
|
||||
assert color.space == 'YCbCr'
|
||||
}
|
||||
|
||||
struct Foo[T] {
|
||||
pub:
|
||||
name string
|
||||
data T
|
||||
}
|
||||
|
||||
fn test_generic_struct() {
|
||||
foo_int := Foo[int]{'bar', 12}
|
||||
foo_enc := json.encode(foo_int)
|
||||
assert foo_enc == '{"name":"bar","data":12}'
|
||||
foo_dec := json.decode[Foo[int]](foo_enc)!
|
||||
assert foo_dec.name == 'bar'
|
||||
assert foo_dec.data == 12
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ enum JobTitle {
|
||||
worker
|
||||
}
|
||||
|
||||
struct Employee {
|
||||
pub struct Employee {
|
||||
pub mut:
|
||||
name string
|
||||
age int
|
||||
@ -17,7 +17,7 @@ pub mut:
|
||||
|
||||
const currency_id = 'cconst'
|
||||
|
||||
struct Price {
|
||||
pub struct Price {
|
||||
net f64
|
||||
currency_id string [json: currencyId] = currency_id
|
||||
}
|
||||
@ -55,7 +55,7 @@ struct Item {
|
||||
}
|
||||
|
||||
enum Animal {
|
||||
dog Will be encoded as `0`
|
||||
dog // Will be encoded as `0`
|
||||
cat
|
||||
}
|
||||
|
||||
@ -94,16 +94,6 @@ fn test_encode_decode_sumtype() {
|
||||
assert (game.other[4] as time.Time).unix_time() == (dec.other[4] as time.Time).unix_time()
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
x string
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_generic() {
|
||||
result := bar<Bar>('{"x":"test"}') or { Bar{} }
|
||||
assert result.x == 'test'
|
||||
}
|
||||
|
||||
struct User2 {
|
||||
mut:
|
||||
age int
|
||||
@ -111,7 +101,7 @@ mut:
|
||||
reg_date time.Time
|
||||
}
|
||||
|
||||
User struct needs to be `pub mut` for now in order to access and manipulate values
|
||||
// User struct needs to be `pub mut` for now in order to access and manipulate values
|
||||
struct User {
|
||||
pub mut:
|
||||
age int
|
||||
@ -155,15 +145,6 @@ pub mut:
|
||||
point string [raw]
|
||||
}
|
||||
|
||||
fn test_raw_json_field() {
|
||||
color := json.decode<Color>('{"space": "YCbCr", "point": {"Y": 123}}') or {
|
||||
assert false
|
||||
Color{}
|
||||
}
|
||||
assert color.point == '{"Y":123}'
|
||||
assert color.space == 'YCbCr'
|
||||
}
|
||||
|
||||
//! FIX: returning 0
|
||||
fn test_bad_raw_json_field() {
|
||||
color := json.decode<Color>('{"space": "YCbCr"}') or {
|
||||
@ -282,22 +263,6 @@ fn test_nested_type() {
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo[T] {
|
||||
pub:
|
||||
name string
|
||||
data T
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_generic_struct() {
|
||||
foo_int := Foo[int]{'bar', 12}
|
||||
foo_enc := json.encode(foo_int)
|
||||
assert foo_enc == '{"name":"bar","data":12}'
|
||||
foo_dec := json.decode[Foo[int]](foo_enc)!
|
||||
assert foo_dec.name == 'bar'
|
||||
assert foo_dec.data == 12
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_errors() {
|
||||
invalid_array := fn () {
|
||||
|
Loading…
Reference in New Issue
Block a user