mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
x.json2: generic-based encoder (finish PR#15137) (#16464)
This commit is contained in:
@@ -2,5 +2,5 @@ import x.json2
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
x := '[[],[],[]]'
|
x := '[[],[],[]]'
|
||||||
println(json2.raw_decode(x)?)
|
println(json2.raw_decode(x)!)
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,17 @@
|
|||||||
module json2
|
module json2
|
||||||
|
|
||||||
// `Any` is a sum type that lists the possible types to be decoded and used.
|
// `Any` is a sum type that lists the possible types to be decoded and used.
|
||||||
pub type Any = Null | []Any | bool | f32 | f64 | i64 | int | map[string]Any | string | u64
|
pub type Any = Null
|
||||||
|
| []Any
|
||||||
|
| []int
|
||||||
|
| bool
|
||||||
|
| f32
|
||||||
|
| f64
|
||||||
|
| i64
|
||||||
|
| int
|
||||||
|
| map[string]Any
|
||||||
|
| string
|
||||||
|
| u64
|
||||||
|
|
||||||
// `Null` struct is a simple representation of the `null` value in JSON.
|
// `Null` struct is a simple representation of the `null` value in JSON.
|
||||||
pub struct Null {
|
pub struct Null {
|
||||||
|
@@ -14,6 +14,8 @@ pub struct Encoder {
|
|||||||
escape_unicode bool = true
|
escape_unicode bool = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const default_encoder = Encoder{}
|
||||||
|
|
||||||
// byte array versions of the most common tokens/chars
|
// byte array versions of the most common tokens/chars
|
||||||
// to avoid reallocations
|
// to avoid reallocations
|
||||||
const null_in_bytes = 'null'.bytes()
|
const null_in_bytes = 'null'.bytes()
|
||||||
@@ -37,9 +39,9 @@ const quote_bytes = [u8(`"`)]
|
|||||||
const escaped_chars = [(r'\b').bytes(), (r'\f').bytes(), (r'\n').bytes(),
|
const escaped_chars = [(r'\b').bytes(), (r'\f').bytes(), (r'\n').bytes(),
|
||||||
(r'\r').bytes(), (r'\t').bytes()]
|
(r'\r').bytes(), (r'\t').bytes()]
|
||||||
|
|
||||||
// encode_value encodes an `Any` value to the specific writer.
|
// encode_value encodes a value to the specific writer.
|
||||||
pub fn (e &Encoder) encode_value(f Any, mut wr io.Writer) ! {
|
pub fn (e &Encoder) encode_value<T>(val T, mut wr io.Writer) ! {
|
||||||
e.encode_value_with_level(f, 1, mut wr)!
|
e.encode_value_with_level<T>(val, 1, mut wr)!
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (e &Encoder) encode_newline(level int, mut wr io.Writer) ! {
|
fn (e &Encoder) encode_newline(level int, mut wr io.Writer) ! {
|
||||||
@@ -51,24 +53,24 @@ fn (e &Encoder) encode_newline(level int, mut wr io.Writer) ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (e &Encoder) encode_value_with_level(f Any, level int, mut wr io.Writer) ! {
|
fn (e &Encoder) encode_any(val Any, level int, mut wr io.Writer) ! {
|
||||||
match f {
|
match val {
|
||||||
string {
|
string {
|
||||||
e.encode_string(f, mut wr)!
|
e.encode_string(val, mut wr)!
|
||||||
}
|
}
|
||||||
bool {
|
bool {
|
||||||
if f == true {
|
if val == true {
|
||||||
wr.write(json2.true_in_bytes)!
|
wr.write(json2.true_in_bytes)!
|
||||||
} else {
|
} else {
|
||||||
wr.write(json2.false_in_bytes)!
|
wr.write(json2.false_in_bytes)!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int, u64, i64 {
|
int, u64, i64 {
|
||||||
wr.write(f.str().bytes())!
|
wr.write(val.str().bytes())!
|
||||||
}
|
}
|
||||||
f32, f64 {
|
f32, f64 {
|
||||||
$if !nofloat ? {
|
$if !nofloat ? {
|
||||||
str_float := f.str().bytes()
|
str_float := val.str().bytes()
|
||||||
wr.write(str_float)!
|
wr.write(str_float)!
|
||||||
if str_float[str_float.len - 1] == `.` {
|
if str_float[str_float.len - 1] == `.` {
|
||||||
wr.write(json2.zero_in_bytes)!
|
wr.write(json2.zero_in_bytes)!
|
||||||
@@ -80,7 +82,7 @@ fn (e &Encoder) encode_value_with_level(f Any, level int, mut wr io.Writer) ! {
|
|||||||
map[string]Any {
|
map[string]Any {
|
||||||
wr.write([u8(`{`)])!
|
wr.write([u8(`{`)])!
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for k, v in f {
|
for k, v in val {
|
||||||
e.encode_newline(level, mut wr)!
|
e.encode_newline(level, mut wr)!
|
||||||
e.encode_string(k, mut wr)!
|
e.encode_string(k, mut wr)!
|
||||||
wr.write(json2.colon_bytes)!
|
wr.write(json2.colon_bytes)!
|
||||||
@@ -88,7 +90,7 @@ fn (e &Encoder) encode_value_with_level(f Any, level int, mut wr io.Writer) ! {
|
|||||||
wr.write(json2.space_bytes)!
|
wr.write(json2.space_bytes)!
|
||||||
}
|
}
|
||||||
e.encode_value_with_level(v, level + 1, mut wr)!
|
e.encode_value_with_level(v, level + 1, mut wr)!
|
||||||
if i < f.len - 1 {
|
if i < val.len - 1 {
|
||||||
wr.write(json2.comma_bytes)!
|
wr.write(json2.comma_bytes)!
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
@@ -98,13 +100,27 @@ fn (e &Encoder) encode_value_with_level(f Any, level int, mut wr io.Writer) ! {
|
|||||||
}
|
}
|
||||||
[]Any {
|
[]Any {
|
||||||
wr.write([u8(`[`)])!
|
wr.write([u8(`[`)])!
|
||||||
for i, v in f {
|
for i in 0 .. val.len {
|
||||||
e.encode_newline(level, mut wr)!
|
e.encode_newline(level, mut wr)!
|
||||||
e.encode_value_with_level(v, level + 1, mut wr)!
|
e.encode_value_with_level(val[i], level + 1, mut wr)!
|
||||||
if i < f.len - 1 {
|
if i < val.len - 1 {
|
||||||
wr.write(json2.comma_bytes)!
|
wr.write(json2.comma_bytes)!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.encode_newline(level - 1, mut wr)!
|
||||||
|
wr.write([u8(`]`)])!
|
||||||
|
}
|
||||||
|
[]int {
|
||||||
|
wr.write([u8(`[`)])!
|
||||||
|
for i in 0 .. val.len {
|
||||||
|
e.encode_newline(level, mut wr)!
|
||||||
|
e.encode_value_with_level(val[i], level + 1, mut wr)!
|
||||||
|
if i < val.len - 1 {
|
||||||
|
wr.write(json2.comma_bytes)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e.encode_newline(level - 1, mut wr)!
|
e.encode_newline(level - 1, mut wr)!
|
||||||
wr.write([u8(`]`)])!
|
wr.write([u8(`]`)])!
|
||||||
}
|
}
|
||||||
@@ -114,6 +130,85 @@ fn (e &Encoder) encode_value_with_level(f Any, level int, mut wr io.Writer) ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (e &Encoder) encode_value_with_level<T>(val T, level int, mut wr io.Writer) ! {
|
||||||
|
$if T is string {
|
||||||
|
e.encode_string(val, mut wr)!
|
||||||
|
} $else $if T is Any {
|
||||||
|
e.encode_any(val, level, mut wr)!
|
||||||
|
} $else $if T is map[string]Any {
|
||||||
|
// weird quirk but val is destructured immediately to Any
|
||||||
|
e.encode_any(val, level, mut wr)!
|
||||||
|
} $else $if T is []Any {
|
||||||
|
e.encode_any(val, level, mut wr)!
|
||||||
|
} $else $if T is Null || T is bool || T is f32 || T is f64 || T is i64 || T is int || T is u64 {
|
||||||
|
e.encode_any(val, level, mut wr)!
|
||||||
|
} $else $if T is Encodable {
|
||||||
|
wr.write(val.json_str().bytes())!
|
||||||
|
} $else $if T is []int {
|
||||||
|
// wr.write(val.str)!
|
||||||
|
e.encode_any(val, level, mut wr)!
|
||||||
|
} $else $if T is $Struct {
|
||||||
|
e.encode_struct(val, level, mut wr)!
|
||||||
|
} $else $if T is $Enum {
|
||||||
|
e.encode_any(Any(int(val)), level, mut wr)!
|
||||||
|
} $else {
|
||||||
|
return error('cannot encode value with ${typeof(val).name} type')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (e &Encoder) encode_struct<U>(val U, level int, mut wr io.Writer) ! {
|
||||||
|
wr.write([u8(`{`)])!
|
||||||
|
mut i := 0
|
||||||
|
mut fields_len := 0
|
||||||
|
$for _ in U.fields {
|
||||||
|
fields_len++
|
||||||
|
}
|
||||||
|
$for field in U.fields {
|
||||||
|
mut json_name := ''
|
||||||
|
for attr in field.attrs {
|
||||||
|
if attr.contains('json: ') {
|
||||||
|
json_name = attr.replace('json: ', '')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.encode_newline(level, mut wr)!
|
||||||
|
if json_name != '' {
|
||||||
|
e.encode_string(json_name, mut wr)!
|
||||||
|
} else {
|
||||||
|
e.encode_string(field.name, mut wr)!
|
||||||
|
}
|
||||||
|
wr.write(json2.colon_bytes)!
|
||||||
|
if e.newline != 0 {
|
||||||
|
wr.write(json2.space_bytes)!
|
||||||
|
}
|
||||||
|
field_value := val.$(field.name)
|
||||||
|
e.encode_value_with_level(field_value, level + 1, mut wr)!
|
||||||
|
if i < fields_len - 1 {
|
||||||
|
wr.write(json2.comma_bytes)!
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
e.encode_newline(level - 1, mut wr)!
|
||||||
|
wr.write([u8(`}`)])!
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (e &Encoder) encode_array<U>(val U, level int, mut wr io.Writer) ! {
|
||||||
|
$if U is $Array {
|
||||||
|
wr.write([u8(`[`)])!
|
||||||
|
for i in 0 .. val.len {
|
||||||
|
e.encode_newline(level, mut wr)!
|
||||||
|
e.encode_value_with_level(&val[i], level + 1, mut wr)!
|
||||||
|
if i < val.len - 1 {
|
||||||
|
wr.write(json2.comma_bytes)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.encode_newline(level - 1, mut wr)!
|
||||||
|
wr.write([u8(`]`)])!
|
||||||
|
} $else {
|
||||||
|
return error('encoded array value is not an array')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// str returns the JSON string representation of the `map[string]Any` type.
|
// str returns the JSON string representation of the `map[string]Any` type.
|
||||||
pub fn (f map[string]Any) str() string {
|
pub fn (f map[string]Any) str() string {
|
||||||
return Any(f).json_str()
|
return Any(f).json_str()
|
||||||
@@ -137,13 +232,7 @@ pub fn (f Any) str() string {
|
|||||||
// json_str returns the JSON string representation of the `Any` type.
|
// json_str returns the JSON string representation of the `Any` type.
|
||||||
[manualfree]
|
[manualfree]
|
||||||
pub fn (f Any) json_str() string {
|
pub fn (f Any) json_str() string {
|
||||||
mut sb := strings.new_builder(4096)
|
return encode(f)
|
||||||
defer {
|
|
||||||
unsafe { sb.free() }
|
|
||||||
}
|
|
||||||
mut enc := Encoder{}
|
|
||||||
enc.encode_value(f, mut sb) or { return '' }
|
|
||||||
return sb.str()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prettify_json_str returns the pretty-formatted JSON string representation of the `Any` type.
|
// prettify_json_str returns the pretty-formatted JSON string representation of the `Any` type.
|
||||||
@@ -157,7 +246,7 @@ pub fn (f Any) prettify_json_str() string {
|
|||||||
newline: `\n`
|
newline: `\n`
|
||||||
newline_spaces_count: 4
|
newline_spaces_count: 4
|
||||||
}
|
}
|
||||||
enc.encode_value(f, mut sb) or { return '' }
|
enc.encode_value(f, mut sb) or {}
|
||||||
return sb.str()
|
return sb.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,19 +38,20 @@ fn test_json_string_non_ascii() {
|
|||||||
|
|
||||||
fn test_utf8_strings_are_not_modified() {
|
fn test_utf8_strings_are_not_modified() {
|
||||||
original := '{"s":"Schilddrüsenerkrankungen"}'
|
original := '{"s":"Schilddrüsenerkrankungen"}'
|
||||||
// dump(original)
|
|
||||||
deresult := json2.raw_decode(original)!
|
deresult := json2.raw_decode(original)!
|
||||||
// dump(deresult)
|
|
||||||
assert deresult.str() == original
|
assert deresult.str() == original
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_encoder_unescaped_utf32() {
|
fn test_encoder_unescaped_utf32() ! {
|
||||||
jap_text := json2.Any('ひらがな')
|
jap_text := json2.Any('ひらがな')
|
||||||
enc := json2.Encoder{
|
enc := json2.Encoder{
|
||||||
escape_unicode: false
|
escape_unicode: false
|
||||||
}
|
}
|
||||||
|
|
||||||
mut sb := strings.new_builder(20)
|
mut sb := strings.new_builder(20)
|
||||||
|
defer {
|
||||||
|
unsafe { sb.free() }
|
||||||
|
}
|
||||||
enc.encode_value(jap_text, mut sb)!
|
enc.encode_value(jap_text, mut sb)!
|
||||||
|
|
||||||
assert sb.str() == '"${jap_text}"'
|
assert sb.str() == '"${jap_text}"'
|
||||||
@@ -74,6 +75,9 @@ fn test_encoder_prettify() {
|
|||||||
newline_spaces_count: 2
|
newline_spaces_count: 2
|
||||||
}
|
}
|
||||||
mut sb := strings.new_builder(20)
|
mut sb := strings.new_builder(20)
|
||||||
|
defer {
|
||||||
|
unsafe { sb.free() }
|
||||||
|
}
|
||||||
enc.encode_value(obj, mut sb)!
|
enc.encode_value(obj, mut sb)!
|
||||||
assert sb.str() == '{
|
assert sb.str() == '{
|
||||||
"hello": "world",
|
"hello": "world",
|
||||||
@@ -88,3 +92,34 @@ fn test_encoder_prettify() {
|
|||||||
}
|
}
|
||||||
}'
|
}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Test {
|
||||||
|
val string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_struct() {
|
||||||
|
enc := json2.encode(Test{'hello!'})
|
||||||
|
assert enc == '{"val":"hello!"}'
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Uri {
|
||||||
|
protocol string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (u Uri) json_str() string {
|
||||||
|
return '"${u.protocol}://${u.path}"'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_encodable() {
|
||||||
|
assert json2.encode(Uri{'file', 'path/to/file'}) == '"file://path/to/file"'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_array() {
|
||||||
|
assert json2.encode([1, 2, 3]) == '[1,2,3]'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_simple() {
|
||||||
|
assert json2.encode('hello!') == '"hello!"'
|
||||||
|
assert json2.encode(1) == '1'
|
||||||
|
}
|
||||||
|
@@ -3,13 +3,18 @@
|
|||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module json2
|
module json2
|
||||||
|
|
||||||
|
import strings
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
null = Null{}
|
null = Null{}
|
||||||
)
|
)
|
||||||
|
|
||||||
pub interface Serializable {
|
pub interface Decodable {
|
||||||
from_json(f Any)
|
from_json(f Any)
|
||||||
to_json() string
|
}
|
||||||
|
|
||||||
|
pub interface Encodable {
|
||||||
|
json_str() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decodes a JSON string into an `Any` type. Returns an option.
|
// Decodes a JSON string into an `Any` type. Returns an option.
|
||||||
@@ -33,8 +38,16 @@ pub fn decode<T>(src string) !T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// encode is a generic function that encodes a type into a JSON string.
|
// encode is a generic function that encodes a type into a JSON string.
|
||||||
pub fn encode<T>(typ T) string {
|
pub fn encode<T>(val T) string {
|
||||||
return typ.to_json()
|
mut sb := strings.new_builder(64)
|
||||||
|
defer {
|
||||||
|
unsafe { sb.free() }
|
||||||
|
}
|
||||||
|
default_encoder.encode_value(val, mut sb) or {
|
||||||
|
dump(err)
|
||||||
|
default_encoder.encode_value<Null>(json2.null, mut sb) or {}
|
||||||
|
}
|
||||||
|
return sb.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
// as_map uses `Any` as a map.
|
// as_map uses `Any` as a map.
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import x.json2
|
import x.json2
|
||||||
|
import time
|
||||||
|
|
||||||
enum JobTitle {
|
enum JobTitle {
|
||||||
manager
|
manager
|
||||||
@@ -45,14 +46,12 @@ fn (mut e Employee) from_json(any json2.Any) {
|
|||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
x := Employee{'Peter', 28, 95000.5, .worker}
|
x := Employee{'Peter', 28, 95000.5, .worker}
|
||||||
s := json2.encode<Employee>(x)
|
s := json2.encode<Employee>(x)
|
||||||
eprintln('Employee x: ${s}')
|
|
||||||
assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":2}'
|
assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":2}'
|
||||||
y := json2.decode<Employee>(s) or {
|
y := json2.decode<Employee>(s) or {
|
||||||
println(err)
|
println(err)
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
eprintln('Employee y: ${y}')
|
|
||||||
assert y.name == 'Peter'
|
assert y.name == 'Peter'
|
||||||
assert y.age == 28
|
assert y.age == 28
|
||||||
assert y.salary == 95000.5
|
assert y.salary == 95000.5
|
||||||
@@ -83,7 +82,6 @@ fn test_character_unescape() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
lines := obj.as_map()
|
lines := obj.as_map()
|
||||||
eprintln('${lines}')
|
|
||||||
assert lines['newline'] or { 0 }.str() == 'new\nline'
|
assert lines['newline'] or { 0 }.str() == 'new\nline'
|
||||||
assert lines['tab'] or { 0 }.str() == '\ttab'
|
assert lines['tab'] or { 0 }.str() == '\ttab'
|
||||||
assert lines['backslash'] or { 0 }.str() == 'back\\slash'
|
assert lines['backslash'] or { 0 }.str() == 'back\\slash'
|
||||||
@@ -91,12 +89,6 @@ fn test_character_unescape() {
|
|||||||
assert lines['slash'] or { 0 }.str() == '/dev/null'
|
assert lines['slash'] or { 0 }.str() == '/dev/null'
|
||||||
}
|
}
|
||||||
|
|
||||||
struct User2 {
|
|
||||||
pub mut:
|
|
||||||
age int
|
|
||||||
nums []int
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut u User2) from_json(an json2.Any) {
|
fn (mut u User2) from_json(an json2.Any) {
|
||||||
mp := an.as_map()
|
mp := an.as_map()
|
||||||
mut js_field_name := ''
|
mut js_field_name := ''
|
||||||
@@ -116,6 +108,13 @@ fn (mut u User2) from_json(an json2.Any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// User struct needs to be `pub mut` for now in order to access and manipulate values
|
||||||
struct User {
|
struct User {
|
||||||
pub mut:
|
pub mut:
|
||||||
@@ -166,17 +165,8 @@ fn (u User) to_json() string {
|
|||||||
|
|
||||||
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 := json2.decode<User2>(s) or {
|
u2 := json2.decode<User2>(s)!
|
||||||
println(err)
|
u := json2.decode<User>(s)!
|
||||||
assert false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
println(u2)
|
|
||||||
u := json2.decode<User>(s) or {
|
|
||||||
println(err)
|
|
||||||
assert false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
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
|
||||||
@@ -188,8 +178,26 @@ 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 := json2.encode(user)
|
||||||
|
// // println(s) //{"age":25,"nums":[],"reg_date":{"year":2020,"month":12,"day":22,"hour":7,"minute":23,"second":0,"microsecond":0,"unix":1608621780,"is_local":false}}
|
||||||
|
// assert s.contains('"reg_date":1608621780')
|
||||||
|
// user2 := json2.decode<User2>(s)!
|
||||||
|
// assert user2.reg_date.str() == '2020-12-22 07:23:00'
|
||||||
|
// // println(user2)
|
||||||
|
// // println(user2.reg_date)
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn (mut u User) foo() string {
|
||||||
|
return json2.encode(u)
|
||||||
|
}
|
||||||
|
|
||||||
fn test_encode_user() {
|
fn test_encode_user() {
|
||||||
usr := User{
|
mut usr := User{
|
||||||
age: 10
|
age: 10
|
||||||
nums: [1, 2, 3]
|
nums: [1, 2, 3]
|
||||||
last_name: 'Johnson'
|
last_name: 'Johnson'
|
||||||
@@ -200,6 +208,8 @@ fn test_encode_user() {
|
|||||||
expected := '{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"foo"}'
|
expected := '{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"foo"}'
|
||||||
out := json2.encode<User>(usr)
|
out := json2.encode<User>(usr)
|
||||||
assert out == expected
|
assert out == expected
|
||||||
|
// Test json.encode on mutable pointers
|
||||||
|
assert usr.foo() == expected
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
@@ -237,9 +247,8 @@ struct Country {
|
|||||||
cities []City
|
cities []City
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_struct_in_struct() {
|
fn test_struct_in_struct() {
|
||||||
country := json.decode(Country, '{ "name": "UK", "cities": [{"name":"London"}, {"name":"Manchester"}]}') or {
|
country := json2.decode<Country>('{ "name": "UK", "cities": [{"name":"London"}, {"name":"Manchester"}]}') or {
|
||||||
assert false
|
assert false
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user