import x.json2 as json import time enum JobTitle { manager executive worker } struct Employee { pub mut: name string age int salary f32 title JobTitle } struct EmployeeOp { pub mut: name ?string = none last_name ?string = none age ?int salary f32 title JobTitle } fn (e Employee) to_json() string { mut mp := map[string]json.Any{} mp['name'] = json.Any(e.name) mp['age'] = json.Any(e.age) mp['salary'] = json.Any(e.salary) mp['title'] = json.Any(int(e.title)) /* $for field in Employee.fields { d := e.$(field.name) $if field.typ is JobTitle { mp[field.name] = json.encode(d) } $else { mp[field.name] = d } } */ 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} // x := EmployeeOp{ // name: 'vshfvhsd' // } // s := json.encode(x) // assert s == '{"name":"vshfvhsd","age":0,"salary":0.0,"title":0.0}' // // y := json.decode(s) or { // // println(err) // // assert false // // return // // } // // assert y.name == 'Peter' // // assert y.age == 28 // // assert y.salary == 95000.5 // // assert y.title == .worker // } fn test_fast_raw_decode() { s := '{"name":"Peter","age":28,"salary":95000.5,"title":2}' o := json.fast_raw_decode(s) or { assert false json.Any(json.null) } str := o.str() assert str == '{"name":"Peter","age":"28","salary":"95000.5","title":"2"}' } fn test_character_unescape() { message := r'{ "newline": "new\nline", "tab": "\ttab", "backslash": "back\\slash", "quotes": "\"quotes\"", "slash":"\/dev\/null" }' mut obj := json.raw_decode(message) or { println(err) assert false return } lines := obj.as_map() assert lines['newline'] or { 0 }.str() == 'new\nline' assert lines['tab'] or { 0 }.str() == '\ttab' assert lines['backslash'] or { 0 }.str() == 'back\\slash' assert lines['quotes'] or { 0 }.str() == '"quotes"' 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 User2 { pub mut: age int nums []int reg_date time.Time } 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 {} } } }