mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin, cgen: support FieldData.unaliased_typ, use it for generalising x.json2 (able to encode type aliased struct fields) (#16469)
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import x.json2 as json
|
||||
|
||||
struct TestTwin {
|
||||
id int
|
||||
seed string
|
||||
pubkey string
|
||||
}
|
||||
|
||||
struct TestTwins {
|
||||
mut:
|
||||
twins []TestTwin [required]
|
||||
}
|
||||
|
||||
fn test_json_decode_fails_to_decode_unrecognised_array_of_dicts() {
|
||||
data := '[{"twins":[{"id":123,"seed":"abcde","pubkey":"xyzasd"},{"id":456,"seed":"dfgdfgdfgd","pubkey":"skjldskljh45sdf"}]}]'
|
||||
json.decode<TestTwins>(data) or {
|
||||
assert err.msg() == "expected field 'twins' is missing"
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_json_decode_works_with_a_dict_of_arrays() {
|
||||
data := '{"twins":[{"id":123,"seed":"abcde","pubkey":"xyzasd"},{"id":456,"seed":"dfgdfgdfgd","pubkey":"skjldskljh45sdf"}]}'
|
||||
res := json.decode<TestTwins>(data) or {
|
||||
assert false
|
||||
exit(1)
|
||||
}
|
||||
assert res.twins[0].id == 123
|
||||
assert res.twins[0].seed == 'abcde'
|
||||
assert res.twins[0].pubkey == 'xyzasd'
|
||||
assert res.twins[1].id == 456
|
||||
assert res.twins[1].seed == 'dfgdfgdfgd'
|
||||
assert res.twins[1].pubkey == 'skjldskljh45sdf'
|
||||
}
|
||||
|
||||
struct Mount {
|
||||
size u64
|
||||
}
|
||||
|
||||
fn test_decode_u64() {
|
||||
data := '{"size": 10737418240}'
|
||||
m := json.decode<Mount>(data)!
|
||||
assert m.size == 10737418240
|
||||
// println(m)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
pub struct Comment {
|
||||
pub mut:
|
||||
id string
|
||||
comment string
|
||||
}
|
||||
|
||||
pub struct Task {
|
||||
mut:
|
||||
description string
|
||||
id int
|
||||
total_comments int
|
||||
file_name string [skip]
|
||||
comments []Comment [skip]
|
||||
}
|
||||
|
||||
fn test_skip_fields_should_be_initialised_by_json_decode() {
|
||||
data := '{"total_comments": 55, "id": 123}'
|
||||
mut task := json.decode<Task>(data)!
|
||||
assert task.id == 123
|
||||
assert task.total_comments == 55
|
||||
assert task.comments == []
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
struct DbConfig {
|
||||
host string
|
||||
dbname string
|
||||
user string
|
||||
}
|
||||
|
||||
fn test_decode_error_message_should_have_enough_context_empty() {
|
||||
json.decode<DbConfig>('') or {
|
||||
assert err.msg().len < 2
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_decode_error_message_should_have_enough_context_just_brace() {
|
||||
json.decode<DbConfig>('{') or {
|
||||
assert err.msg() == '{'
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_decode_error_message_should_have_enough_context_trailing_comma_at_end() {
|
||||
txt := '{
|
||||
"host": "localhost",
|
||||
"dbname": "alex",
|
||||
"user": "alex",
|
||||
}'
|
||||
json.decode<DbConfig>(txt) or {
|
||||
assert err.msg() == ' "user": "alex",\n}'
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
|
||||
fn test_decode_error_message_should_have_enough_context_in_the_middle() {
|
||||
txt := '{"host": "localhost", "dbname": "alex" "user": "alex", "port": "1234"}'
|
||||
json.decode<DbConfig>(txt) or {
|
||||
assert err.msg() == 'ost", "dbname": "alex" "user":'
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import x.json2 as json
|
||||
|
||||
struct TodoDto {
|
||||
foo int
|
||||
}
|
||||
|
||||
fn test_decode_with_encode_arg() {
|
||||
body := TodoDto{}
|
||||
ret := json.decode<TodoDto>(json.encode(body))!
|
||||
println(ret)
|
||||
assert ret.foo == 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import x.json2 as json
|
||||
|
||||
struct Result<T> {
|
||||
ok bool
|
||||
result T
|
||||
}
|
||||
|
||||
struct User {
|
||||
id int
|
||||
username string
|
||||
}
|
||||
|
||||
fn func<T>() !T {
|
||||
text := '{"ok": true, "result":{"id":37467243, "username": "ciao"}}'
|
||||
a := json.decode<Result<T>>(text)!
|
||||
return a.result
|
||||
}
|
||||
|
||||
fn test_decode_with_generic_struct() {
|
||||
ret := func<User>()!
|
||||
println(ret)
|
||||
assert ret.id == 37467243
|
||||
assert ret.username == 'ciao'
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import x.json2 as json
|
||||
import os
|
||||
|
||||
struct DbConfig {}
|
||||
|
||||
fn test_json_decode_with_optional_arg() {
|
||||
if ret := print_info() {
|
||||
println(ret)
|
||||
} else {
|
||||
println(err)
|
||||
}
|
||||
assert true
|
||||
}
|
||||
|
||||
fn print_info() !string {
|
||||
dbconf := json.decode<DbConfig>(os.read_file('dbconf.json')!)!
|
||||
println(dbconf)
|
||||
return '${dbconf}'
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import x.json2 as json
|
||||
|
||||
type Test = []bool | []int | []string | string
|
||||
|
||||
struct Some {
|
||||
t Test
|
||||
}
|
||||
|
||||
fn test_json_decode_with_sumtype() {
|
||||
v1 := json.decode<Some>('{"t": ["string", "string2"]}')!
|
||||
println(v1)
|
||||
assert v1.t == Test(['string', 'string2'])
|
||||
|
||||
v2 := json.decode<Some>('{"t": [11, 22]}')!
|
||||
println(v2)
|
||||
assert v2.t == Test([11, 22])
|
||||
|
||||
v3 := json.decode<Some>('{"t": [true, false]}')!
|
||||
println(v3)
|
||||
assert v3.t == Test([true, false])
|
||||
}
|
||||
149
vlib/x/json2/json_module_compatibility_test/json_test.v
Normal file
149
vlib/x/json2/json_module_compatibility_test/json_test.v
Normal file
@@ -0,0 +1,149 @@
|
||||
import x.json2 as json
|
||||
import time
|
||||
|
||||
enum JobTitle {
|
||||
manager
|
||||
executive
|
||||
worker
|
||||
}
|
||||
|
||||
struct Employee {
|
||||
pub mut:
|
||||
name string
|
||||
age int
|
||||
salary f32
|
||||
title JobTitle
|
||||
sub_employee SubEmployee
|
||||
}
|
||||
|
||||
struct SubEmployee {
|
||||
pub mut:
|
||||
name string
|
||||
age int
|
||||
salary f32
|
||||
title JobTitle
|
||||
}
|
||||
|
||||
fn test_simple() {
|
||||
sub_employee := SubEmployee{
|
||||
name: 'João'
|
||||
}
|
||||
x := Employee{'Peter', 28, 95000.5, .worker, sub_employee}
|
||||
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
|
||||
}
|
||||
|
||||
// const currency_id = 'cconst'
|
||||
|
||||
// struct Price {
|
||||
// net f64
|
||||
// currency_id string [json: currencyId] = currency_id
|
||||
// }
|
||||
|
||||
// struct User2 {
|
||||
// mut:
|
||||
// age int
|
||||
// nums []int
|
||||
// reg_date time.Time
|
||||
// }
|
||||
|
||||
// // User struct needs to be `pub mut` for now in order to access and manipulate values
|
||||
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) foo() string {
|
||||
return json.encode(u)
|
||||
}
|
||||
|
||||
fn test_encode_user() {
|
||||
mut usr := User{
|
||||
age: 10
|
||||
nums: [1, 2, 3]
|
||||
last_name: 'Johnson'
|
||||
is_registered: true
|
||||
typ: 0
|
||||
pets: 'foo'
|
||||
}
|
||||
expected := '{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"foo"}'
|
||||
out := json.encode<User>(usr)
|
||||
// println(out)
|
||||
assert out == expected
|
||||
// Test json.encode on mutable pointers
|
||||
assert usr.foo() == expected
|
||||
}
|
||||
|
||||
// struct Color {
|
||||
// pub mut:
|
||||
// space string
|
||||
// point string [raw]
|
||||
// }
|
||||
|
||||
fn test_encode_map() {
|
||||
expected := '{"one":1,"two":2,"three":3,"four":4}'
|
||||
numbers := {
|
||||
'one': json.Any(1)
|
||||
'two': json.Any(2)
|
||||
'three': json.Any(3)
|
||||
'four': json.Any(4)
|
||||
}
|
||||
// numbers := {
|
||||
// 'one': 1
|
||||
// 'two': 2
|
||||
// 'three': 3
|
||||
// 'four': 4
|
||||
// }
|
||||
// out := json.encode(numbers)
|
||||
out := numbers.str()
|
||||
assert out == expected
|
||||
}
|
||||
|
||||
type ID = string
|
||||
type GG = int
|
||||
|
||||
struct Message {
|
||||
id ID
|
||||
ij GG
|
||||
}
|
||||
|
||||
fn test_encode_alias_struct() {
|
||||
expected := '{"id":"118499178790780929","ij":999998888}'
|
||||
msg := Message{'118499178790780929', 999998888}
|
||||
out := json.encode<Message>(msg)
|
||||
assert out == expected
|
||||
}
|
||||
|
||||
struct StByteArray {
|
||||
ba []byte
|
||||
}
|
||||
|
||||
fn test_byte_array() {
|
||||
assert json.encode(StByteArray{ ba: [byte(1), 2, 3, 4, 5] }) == '{"ba":[1,2,3,4,5]}'
|
||||
}
|
||||
471
vlib/x/json2/json_module_compatibility_test/json_todo_test.vv
Normal file
471
vlib/x/json2/json_module_compatibility_test/json_todo_test.vv
Normal file
@@ -0,0 +1,471 @@
|
||||
import x.json2 as json
|
||||
import time
|
||||
|
||||
enum JobTitle {
|
||||
manager
|
||||
executive
|
||||
worker
|
||||
}
|
||||
|
||||
struct Employee {
|
||||
pub mut:
|
||||
name string
|
||||
age int
|
||||
salary f32
|
||||
title JobTitle
|
||||
}
|
||||
|
||||
const currency_id = 'cconst'
|
||||
|
||||
struct Price {
|
||||
net f64
|
||||
currency_id string [json: currencyId] = currency_id
|
||||
}
|
||||
|
||||
//! BUGFIX
|
||||
fn test_field_with_default_expr() {
|
||||
data := '[{"net":1},{"net":2,"currencyId":"cjson"}]'
|
||||
prices := json.decode<[]Price>(data)!
|
||||
assert prices == [Price{
|
||||
net: 1
|
||||
currency_id: 'cconst'
|
||||
}, Price{
|
||||
net: 2
|
||||
currency_id: 'cjson'
|
||||
}]
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_decode_top_level_array() {
|
||||
s := '[{"name":"Peter", "age": 29}, {"name":"Bob", "age":31}]'
|
||||
x := json.decode<[]Employee>(s) or { panic(err) }
|
||||
assert x.len == 2
|
||||
assert x[0].name == 'Peter'
|
||||
assert x[0].age == 29
|
||||
assert x[1].name == 'Bob'
|
||||
assert x[1].age == 31
|
||||
}
|
||||
|
||||
struct Human {
|
||||
name string
|
||||
}
|
||||
|
||||
struct Item {
|
||||
tag string
|
||||
}
|
||||
|
||||
enum Animal {
|
||||
dog Will be encoded as `0`
|
||||
cat
|
||||
}
|
||||
|
||||
type Entity = Animal | Human | Item | string | time.Time
|
||||
|
||||
struct SomeGame {
|
||||
title string
|
||||
player Entity
|
||||
other []Entity
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_encode_decode_sumtype() {
|
||||
t := time.now()
|
||||
game := SomeGame{
|
||||
title: 'Super Mega Game'
|
||||
player: Human{'Monke'}
|
||||
other: [
|
||||
Entity(Item{'Pen'}),
|
||||
Item{'Cookie'},
|
||||
Animal.cat,
|
||||
'Stool',
|
||||
t,
|
||||
]
|
||||
}
|
||||
|
||||
enc := json.encode(game)
|
||||
|
||||
assert enc == '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},1,"Stool",{"_type":"Time","value":${t.unix_time()}}]}'
|
||||
|
||||
dec := json.decode<SomeGame>(enc)!
|
||||
|
||||
assert game.title == dec.title
|
||||
assert game.player == dec.player
|
||||
assert (game.other[2] as Animal) == (dec.other[2] as Animal)
|
||||
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
|
||||
nums []int
|
||||
reg_date time.Time
|
||||
}
|
||||
|
||||
User struct needs to be `pub mut` for now in order to access and manipulate values
|
||||
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 test_parse_user() {
|
||||
s := '{"age": 10, "nums": [1,2,3], "type": 1, "lastName": "Johnson", "IsRegistered": true, "pet_animals": {"name": "Bob", "animal": "Dog"}}'
|
||||
u2 := json.decode<User2>(s)!
|
||||
u := json.decode<User>(s)!
|
||||
assert u.age == 10
|
||||
assert u.last_name == 'Johnson'
|
||||
assert u.is_registered == true
|
||||
assert u.nums.len == 3
|
||||
assert u.nums[0] == 1
|
||||
assert u.nums[1] == 2
|
||||
assert u.nums[2] == 3
|
||||
assert u.typ == 1
|
||||
assert u.pets == '{"name":"Bob","animal":"Dog"}'
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
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)
|
||||
assert s.contains('"reg_date":1608621780')
|
||||
user2 := json.decode<User2>(s)!
|
||||
assert user2.reg_date.str() == '2020-12-22 07:23:00'
|
||||
}
|
||||
|
||||
struct Color {
|
||||
pub mut:
|
||||
space string
|
||||
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 {
|
||||
return
|
||||
}
|
||||
assert color.point == ''
|
||||
assert color.space == 'YCbCr'
|
||||
}
|
||||
|
||||
struct City {
|
||||
name string
|
||||
}
|
||||
|
||||
struct Country {
|
||||
cities []City
|
||||
name string
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_struct_in_struct() {
|
||||
country := json.decode<Country>('{ "name": "UK", "cities": [{"name":"London"}, {"name":"Manchester"}]}')!
|
||||
assert country.name == 'UK'
|
||||
assert country.cities.len == 2
|
||||
assert country.cities[0].name == 'London'
|
||||
assert country.cities[1].name == 'Manchester'
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_parse_map() {
|
||||
expected := {
|
||||
'one': 1
|
||||
'two': 2
|
||||
'three': 3
|
||||
'four': 4
|
||||
}
|
||||
out := json.decode<map[string]int>('{"one":1,"two":2,"three":3,"four":4}')!
|
||||
assert out == expected
|
||||
}
|
||||
|
||||
struct Data {
|
||||
countries []Country
|
||||
users map[string]User
|
||||
extra map[string]map[string]int
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_nested_type() {
|
||||
data_expected := '{"countries":[{"cities":[{"name":"London"},{"name":"Manchester"}],"name":"UK"},{"cities":[{"name":"Donlon"},{"name":"Termanches"}],"name":"KU"}],"users":{"Foo":{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"little foo"},"Boo":{"age":20,"nums":[5,3,1],"lastName":"Smith","IsRegistered":false,"type":4,"pet_animals":"little boo"}},"extra":{"2":{"n1":2,"n2":4,"n3":8,"n4":16},"3":{"n1":3,"n2":9,"n3":27,"n4":81}}}'
|
||||
data := Data{
|
||||
countries: [
|
||||
Country{
|
||||
name: 'UK'
|
||||
cities: [City{'London'}, City{'Manchester'}]
|
||||
},
|
||||
Country{
|
||||
name: 'KU'
|
||||
cities: [City{'Donlon'}, City{'Termanches'}]
|
||||
},
|
||||
]
|
||||
users: {
|
||||
'Foo': User{
|
||||
age: 10
|
||||
nums: [1, 2, 3]
|
||||
last_name: 'Johnson'
|
||||
is_registered: true
|
||||
typ: 0
|
||||
pets: 'little foo'
|
||||
}
|
||||
'Boo': User{
|
||||
age: 20
|
||||
nums: [5, 3, 1]
|
||||
last_name: 'Smith'
|
||||
is_registered: false
|
||||
typ: 4
|
||||
pets: 'little boo'
|
||||
}
|
||||
}
|
||||
extra: {
|
||||
'2': {
|
||||
'n1': 2
|
||||
'n2': 4
|
||||
'n3': 8
|
||||
'n4': 16
|
||||
}
|
||||
'3': {
|
||||
'n1': 3
|
||||
'n2': 9
|
||||
'n3': 27
|
||||
'n4': 81
|
||||
}
|
||||
}
|
||||
}
|
||||
out := json.encode(data)
|
||||
assert out == data_expected
|
||||
data2 := json.decode<Data>(data_expected)!
|
||||
assert data2.countries.len == data.countries.len
|
||||
for i in 0 .. 1 {
|
||||
assert data2.countries[i].name == data.countries[i].name
|
||||
assert data2.countries[i].cities.len == data.countries[i].cities.len
|
||||
for j in 0 .. 1 {
|
||||
assert data2.countries[i].cities[j].name == data.countries[i].cities[j].name
|
||||
}
|
||||
}
|
||||
for key, user in data.users {
|
||||
assert data2.users[key].age == user.age
|
||||
assert data2.users[key].nums == user.nums
|
||||
assert data2.users[key].last_name == user.last_name
|
||||
assert data2.users[key].is_registered == user.is_registered
|
||||
assert data2.users[key].typ == user.typ
|
||||
//!assert data2.users[key].pets == user.pets TODO FIX
|
||||
}
|
||||
for k, v in data.extra {
|
||||
for k2, v2 in v {
|
||||
assert data2.extra[k][k2] == v2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 () {
|
||||
data := '{"countries":[{"cities":[{"name":"London"},{"name":"Manchester"}],"name":"UK"},{"cities":{"name":"Donlon"},"name":"KU"}],"users":{"Foo":{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"little foo"},"Boo":{"age":20,"nums":[5,3,1],"lastName":"Smith","IsRegistered":false,"type":4,"pet_animals":"little boo"}},"extra":{"2":{"n1":2,"n2":4,"n3":8,"n4":16},"3":{"n1":3,"n2":9,"n3":27,"n4":81}}}'
|
||||
json.decode<Data>(data) or {
|
||||
assert err.msg().starts_with('Json element is not an array:')
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
invalid_object := fn () {
|
||||
data := '{"countries":[{"cities":[{"name":"London"},{"name":"Manchester"}],"name":"UK"},{"cities":[{"name":"Donlon"},{"name":"Termanches"}],"name":"KU"}],"users":[{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"little foo"},{"age":20,"nums":[5,3,1],"lastName":"Smith","IsRegistered":false,"type":4,"pet_animals":"little boo"}],"extra":{"2":{"n1":2,"n2":4,"n3":8,"n4":16},"3":{"n1":3,"n2":9,"n3":27,"n4":81}}}'
|
||||
json.decode<Data>(data) or {
|
||||
assert err.msg().starts_with('Json element is not an object:')
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
invalid_array()
|
||||
invalid_object()
|
||||
}
|
||||
|
||||
type ID = string
|
||||
type GG = int
|
||||
|
||||
struct Message {
|
||||
id ID
|
||||
ij GG
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_decode_alias_struct() {
|
||||
msg := json.decode<Message>('{"id": "118499178790780929"}')!
|
||||
// hacky way of comparing aliased strings
|
||||
assert msg.id.str() == '118499178790780929'
|
||||
}
|
||||
|
||||
struct List {
|
||||
id int
|
||||
items []string
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_list() {
|
||||
list := json.decode<List>('{"id": 1, "items": ["1", "2"]}')!
|
||||
assert list.id == 1
|
||||
assert list.items == ['1', '2']
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_list_no_id() {
|
||||
list := json.decode<List>('{"items": ["1", "2"]}')!
|
||||
assert list.id == 0
|
||||
assert list.items == ['1', '2']
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_list_no_items() {
|
||||
list := json.decode<List>('{"id": 1}')!
|
||||
assert list.id == 1
|
||||
assert list.items == []
|
||||
}
|
||||
|
||||
struct Info {
|
||||
id int
|
||||
items []string
|
||||
maps map[string]string
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_decode_null_object() {
|
||||
info := json.decode<Info>('{"id": 22, "items": null, "maps": null}')!
|
||||
assert info.id == 22
|
||||
assert '${info.items}' == '[]'
|
||||
assert '${info.maps}' == '{}'
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_decode_missing_maps_field() {
|
||||
info := json.decode<Info>('{"id": 22, "items": null}')!
|
||||
assert info.id == 22
|
||||
assert '${info.items}' == '[]'
|
||||
assert '${info.maps}' == '{}'
|
||||
}
|
||||
|
||||
struct Foo2 {
|
||||
name string
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_pretty() {
|
||||
foo := Foo2{'Bob'}
|
||||
assert json.encode_pretty(foo) == '{
|
||||
"name": "Bob"
|
||||
}'
|
||||
}
|
||||
|
||||
struct Foo3 {
|
||||
name string
|
||||
age int [omitempty]
|
||||
}
|
||||
|
||||
//! BUGFIX - .from_json(res)
|
||||
fn test_omit_empty() {
|
||||
foo := Foo3{'Bob', 0}
|
||||
assert json.encode_pretty(foo) == '{
|
||||
"name": "Bob"
|
||||
}'
|
||||
}
|
||||
|
||||
struct Asdasd {
|
||||
data GamePacketData
|
||||
}
|
||||
|
||||
type GamePacketData = GPEquipItem | GPScale
|
||||
|
||||
struct GPScale {
|
||||
value f32
|
||||
}
|
||||
|
||||
struct GPEquipItem {
|
||||
name string
|
||||
}
|
||||
|
||||
fn create_game_packet(data &GamePacketData) string {
|
||||
return json.encode(data)
|
||||
}
|
||||
|
||||
//! FIX: returning null
|
||||
fn test_encode_sumtype_defined_ahead() {
|
||||
ret := create_game_packet(&GamePacketData(GPScale{}))
|
||||
assert ret == '{"value":0,"_type":"GPScale"}'
|
||||
}
|
||||
|
||||
struct Aa {
|
||||
sub AliasType
|
||||
}
|
||||
|
||||
struct Bb {
|
||||
a int
|
||||
}
|
||||
|
||||
type AliasType = Bb
|
||||
|
||||
//! FIX: returning null
|
||||
fn test_encode_alias_field() {
|
||||
s := json.encode(Aa{
|
||||
sub: Bb{
|
||||
a: 1
|
||||
}
|
||||
})
|
||||
assert s == '{"sub":{"a":1}}'
|
||||
}
|
||||
|
||||
struct APrice {}
|
||||
|
||||
struct Association {
|
||||
association &Association = unsafe { nil }
|
||||
price APrice
|
||||
}
|
||||
|
||||
//! FIX: returning null
|
||||
fn test_encoding_struct_with_pointers() {
|
||||
value := Association{
|
||||
association: &Association{
|
||||
price: APrice{}
|
||||
}
|
||||
price: APrice{}
|
||||
}
|
||||
assert json.encode(value) == '{"association":{"price":{}},"price":{}}'
|
||||
}
|
||||
Reference in New Issue
Block a user