1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

x.json2: refactor/fix json2.encode, add more tests (#16790)

This commit is contained in:
Hitalo Souza 2023-01-05 10:17:38 -03:00 committed by GitHub
parent e3aee748ac
commit 8f217c00e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 207 additions and 113 deletions

View File

@ -56,6 +56,12 @@ fn test_types() {
assert json.encode(StructType[time.Time]{}) == '{"val":"0000-00-00T00:00:00.000Z"}'
assert json.encode(StructType[time.Time]{ val: fixed_time }) == '{"val":"2022-03-11T13:54:25.000Z"}'
assert json.encode(StructType[StructType[int]]{
val: StructType[int]{
val: 1
}
}) == '{"val":{"val":1}}'
}
fn test_optional_types() {
@ -75,6 +81,7 @@ fn test_optional_types() {
assert json.encode(StructTypeOptional[int]{ val: 1 }) == '{"val":1}'
assert json.encode(StructTypeOptional[time.Time]{}) == '{}'
assert json.encode(StructTypeOptional[time.Time]{ val: time.Time{} }) == '{"val":"0000-00-00T00:00:00.000Z"}'
assert json.encode(StructTypeOptional[time.Time]{ val: fixed_time }) == '{"val":"2022-03-11T13:54:25.000Z"}'
}
@ -119,15 +126,63 @@ fn test_array() {
assert json.encode(StructType[[]bool]{ val: [true] }) == '{"val":[true]}'
assert json.encode(StructType[[]bool]{ val: [false] }) == '{"val":[false]}'
assert json.encode(StructType[[]bool]{ val: [false, true, false] }) == '{"val":[false,true,false]}'
array_of_struct := [StructType[bool]{
val: true
}, StructType[bool]{
val: false
}]
assert json.encode(StructType[[]StructType[bool]]{ val: array_of_struct }) == '{"val":[{"val":true},{"val":false}]}'
}
fn test_optional_array() {
assert json.encode(StructTypeOptional[[]int]{ val: none }) == '{}'
assert json.encode(StructTypeOptional[[]string]{}) == '{}'
assert json.encode(StructTypeOptional[[]string]{ val: [] }) == '{"val":[]}'
assert json.encode(StructTypeOptional[[]string]{ val: ['0'] }) == '{"val":["0"]}'
assert json.encode(StructTypeOptional[[]string]{ val: ['1'] }) == '{"val":["1"]}'
assert json.encode(StructTypeOptional[[]int]{}) == '{}'
assert json.encode(StructTypeOptional[[]int]{ val: [] }) == '{"val":[]}'
assert json.encode(StructTypeOptional[[]int]{ val: [0] }) == '{"val":[0]}'
assert json.encode(StructTypeOptional[[]int]{ val: [1] }) == '{"val":[1]}'
assert json.encode(StructTypeOptional[[]int]{ val: [0, 1, 0, 2, 3, 2, 5, 1] }) == '{"val":[0,1,0,2,3,2,5,1]}'
assert json.encode(StructTypeOptional[[]byte]{}) == '{}'
assert json.encode(StructTypeOptional[[]byte]{ val: [] }) == '{"val":[]}'
assert json.encode(StructTypeOptional[[]byte]{ val: [byte(0)] }) == '{"val":[0]}'
assert json.encode(StructTypeOptional[[]byte]{ val: [byte(1)] }) == '{"val":[1]}'
assert json.encode(StructTypeOptional[[]byte]{ val: [byte(0), 1, 0, 2, 3, 2, 5, 1] }) == '{"val":[0,1,0,2,3,2,5,1]}'
assert json.encode(StructTypeOptional[[]i64]{}) == '{}'
assert json.encode(StructTypeOptional[[]i64]{ val: [] }) == '{"val":[]}'
assert json.encode(StructTypeOptional[[]i64]{ val: [i64(0)] }) == '{"val":[0]}'
assert json.encode(StructTypeOptional[[]i64]{ val: [i64(1)] }) == '{"val":[1]}'
assert json.encode(StructTypeOptional[[]i64]{ val: [i64(0), 1, 0, 2, 3, 2, 5, 1] }) == '{"val":[0,1,0,2,3,2,5,1]}'
assert json.encode(StructTypeOptional[[]u64]{}) == '{}'
assert json.encode(StructTypeOptional[[]u64]{ val: [] }) == '{"val":[]}'
assert json.encode(StructTypeOptional[[]u64]{ val: [u64(0)] }) == '{"val":[0]}'
assert json.encode(StructTypeOptional[[]u64]{ val: [u64(1)] }) == '{"val":[1]}'
assert json.encode(StructTypeOptional[[]u64]{ val: [u64(0), 1, 0, 2, 3, 2, 5, 1] }) == '{"val":[0,1,0,2,3,2,5,1]}'
assert json.encode(StructTypeOptional[[]f64]{}) == '{}'
assert json.encode(StructTypeOptional[[]f64]{ val: [] }) == '{"val":[]}'
assert json.encode(StructTypeOptional[[]f64]{ val: [f64(0)] }) == '{"val":[0.0]}'
assert json.encode(StructTypeOptional[[]f64]{ val: [f64(1)] }) == '{"val":[1.0]}'
assert json.encode(StructTypeOptional[[]f64]{ val: [f64(0), 1, 0, 2, 3, 2, 5, 1] }) == '{"val":[0.0,1.0,0.0,2.0,3.0,2.0,5.0,1.0]}'
assert json.encode(StructTypeOptional[[]bool]{}) == '{}'
assert json.encode(StructTypeOptional[[]bool]{ val: [] }) == '{"val":[]}'
assert json.encode(StructTypeOptional[[]bool]{ val: [true] }) == '{"val":[true]}'
assert json.encode(StructTypeOptional[[]bool]{ val: [false] }) == '{"val":[false]}'
assert json.encode(StructTypeOptional[[]bool]{ val: [false, true, false] }) == '{"val":[false,true,false]}'
array_of_struct := [StructType[bool]{
val: true
}, StructType[bool]{
val: false
}]
assert json.encode(StructTypeOptional[[]StructType[bool]]{ val: array_of_struct }) == '{"val":[{"val":true},{"val":false}]}'
}
fn test_alias() {

View File

@ -157,75 +157,58 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
}
$for field in U.fields {
value := val.$(field.name)
is_none := value.str() == 'Option(error: none)'
if !is_none {
mut json_name := ''
for attr in field.attrs {
if attr.contains('json: ') {
json_name = attr.replace('json: ', '')
break
mut json_name := ''
for attr in field.attrs {
if attr.contains('json: ') {
json_name = attr.replace('json: ', '')
break
}
}
$if field.is_optional {
is_none := value.str() == 'Option(error: none)'
if !is_none {
e.encode_newline(level, mut wr)!
if json_name != '' {
e.encode_string(json_name, mut wr)!
} else {
e.encode_string(field.name, mut wr)!
}
}
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)!
}
$if field.typ is string {
e.encode_string(value.str(), mut wr)!
} $else $if field.typ is time.Time {
parsed_time := val.$(field.name) as time.Time
e.encode_string(parsed_time.format_rfc3339(), mut wr)!
} $else $if field.typ is bool || field.typ is f32 || field.typ is f64 || field.typ is i8
|| field.typ is i16 || field.typ is int || field.typ is i64 || field.typ is u8
|| field.typ is u16 || field.typ is u32 || field.typ is u64 {
wr.write(value.str().bytes())!
} $else $if field.typ is []string || field.typ is []bool || field.typ is []f32
|| field.typ is []f64 || field.typ is []i8 || field.typ is []i16
|| field.typ is []int || field.typ is []i64 || field.typ is []u8
|| field.typ is []byte || field.typ is []u16 || field.typ is []u32
|| field.typ is []u64 {
e.encode_array(value, level, mut wr)!
} $else {
}
$if field.typ is ?string {
optional_value := val.$(field.name) as ?string
e.encode_string(optional_value, mut wr)!
} $else $if field.typ is ?bool {
optional_value := val.$(field.name) as ?bool
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?f32 {
optional_value := val.$(field.name) as ?f32
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?f64 {
optional_value := val.$(field.name) as ?f64
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?i8 {
optional_value := val.$(field.name) as ?i8
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?i16 {
optional_value := val.$(field.name) as ?i16
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?int {
optional_value := val.$(field.name) as ?int
wr.write(Any(optional_value).int().str().bytes())!
} $else $if field.typ is ?[]byte {
optional_value := val.$(field.name) as ?[]byte
e.encode_array(optional_value, level, mut wr)!
} $else $if field.typ is ?[]int {
optional_value := val.$(field.name) as ?[]int
e.encode_array(optional_value, level, mut wr)!
} $else $if field.typ is ?time.Time {
optional_value := val.$(field.name) as ?time.Time
parsed_time := optional_value as time.Time
e.encode_string(parsed_time.format_rfc3339(), mut wr)!
} $else {
if field.unaliased_typ != field.typ {
wr.write(json2.colon_bytes)!
if e.newline != 0 {
wr.write(json2.space_bytes)!
}
$if field.typ is ?string {
optional_value := val.$(field.name) as ?string
e.encode_string(optional_value, mut wr)!
} $else $if field.typ is ?bool {
optional_value := val.$(field.name) as ?bool
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?f32 {
optional_value := val.$(field.name) as ?f32
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?f64 {
optional_value := val.$(field.name) as ?f64
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?i8 {
optional_value := val.$(field.name) as ?i8
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?i16 {
optional_value := val.$(field.name) as ?i16
wr.write(Any(optional_value).str().bytes())!
} $else $if field.typ is ?int {
optional_value := val.$(field.name) as ?int
wr.write(Any(optional_value).int().str().bytes())!
} $else $if field.typ is ?time.Time {
optional_value := val.$(field.name) as ?time.Time
parsed_time := optional_value as time.Time
e.encode_string(parsed_time.format_rfc3339(), mut wr)!
} $else $if field.is_array {
e.encode_array(value, level + 1, mut wr)!
} $else $if field.is_alias {
match field.unaliased_typ {
typeof[string]().idx {
e.encode_string(value.str(), mut wr)!
@ -236,67 +219,123 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
wr.write(value.str().bytes())!
}
typeof[[]byte]().idx, typeof[[]int]().idx {
e.encode_array(value, level, mut wr)!
// FIXME - error: could not infer generic type `U` in call to `encode_array`
// e.encode_array(value, level, mut wr)!
}
else {
// e.encode_value_with_level(value, level + 1, mut wr)!
}
}
} $else {
return error('type ${typeof(val).name} cannot be array encoded')
}
}
if i < fields_len - 1 {
wr.write(json2.comma_bytes)!
} $else {
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)!
}
$if field.typ is string {
e.encode_string(value.str(), mut wr)!
} $else $if field.typ is time.Time {
parsed_time := val.$(field.name) as time.Time
e.encode_string(parsed_time.format_rfc3339(), mut wr)!
} $else $if field.typ is bool || field.typ is f32 || field.typ is f64 || field.typ is i8
|| field.typ is i16 || field.typ is int || field.typ is i64 || field.typ is u8
|| field.typ is u16 || field.typ is u32 || field.typ is u64 {
wr.write(value.str().bytes())!
} $else $if field.is_array {
e.encode_array(value, level + 1, mut wr)!
} $else $if field.is_struct {
e.encode_struct(value, level + 1, mut wr)!
} $else $if field.is_alias {
match field.unaliased_typ {
typeof[string]().idx {
e.encode_string(value.str(), mut wr)!
}
typeof[bool]().idx, typeof[f32]().idx, typeof[f64]().idx, typeof[i8]().idx,
typeof[i16]().idx, typeof[int]().idx, typeof[i64]().idx, typeof[u8]().idx,
typeof[u16]().idx, typeof[u32]().idx, typeof[u64]().idx {
wr.write(value.str().bytes())!
}
typeof[[]byte]().idx, typeof[[]int]().idx {
// FIXME - error: could not infer generic type `U` in call to `encode_array`
// e.encode_array(value, level, mut wr)!
}
else {
// e.encode_value_with_level(value, level + 1, mut wr)!
}
}
} $else {
return error('type ${typeof(val).name} cannot be array encoded')
}
i++
}
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)!
fn (e &Encoder) encode_array[U](val []U, level int, mut wr io.Writer) ! {
wr.write([u8(`[`)])!
for i in 0 .. val.len {
e.encode_newline(level, mut wr)!
$if U is []string {
e.encode_any(val[i], level + 1, mut wr)!
} $else $if U is []bool {
e.encode_any(bool(val[i]), level + 1, mut wr)!
} $else $if U is []f32 {
e.encode_any(f32(val[i]), level + 1, mut wr)!
} $else $if U is []f64 {
e.encode_any(f64(val[i]), level + 1, mut wr)!
} $else $if U is []i8 {
e.encode_any(i8(val[i]), level + 1, mut wr)!
} $else $if U is []i16 {
e.encode_any(i16(val[i]), level + 1, mut wr)!
} $else $if U is []int {
e.encode_any(int(val[i]), level + 1, mut wr)!
} $else $if U is []i64 {
e.encode_any(i64(val[i]), level + 1, mut wr)!
} $else $if U is []u8 {
e.encode_any(u8(val[i]), level + 1, mut wr)!
} $else $if U is []byte {
e.encode_any(u8(val[i]), level + 1, mut wr)!
} $else $if U is []u16 {
e.encode_any(u16(val[i]), level + 1, mut wr)!
} $else $if U is []u32 {
e.encode_any(u32(val[i]), level + 1, mut wr)!
} $else $if U is []u64 {
e.encode_any(u64(val[i]), level + 1, mut wr)!
}
if i < val.len - 1 {
wr.write(json2.comma_bytes)!
}
$if U is string {
e.encode_any(val[i], level + 1, mut wr)!
} $else $if U is bool {
e.encode_any(bool(val[i]), level + 1, mut wr)!
} $else $if U is f32 {
e.encode_any(f32(val[i]), level + 1, mut wr)!
} $else $if U is f64 {
e.encode_any(f64(val[i]), level + 1, mut wr)!
} $else $if U is i8 {
e.encode_any(i8(val[i]), level + 1, mut wr)!
} $else $if U is i16 {
e.encode_any(i16(val[i]), level + 1, mut wr)!
} $else $if U is int {
e.encode_any(int(val[i]), level + 1, mut wr)!
} $else $if U is i64 {
e.encode_any(i64(val[i]), level + 1, mut wr)!
} $else $if U is u8 {
e.encode_any(u8(val[i]), level + 1, mut wr)!
} $else $if U is byte {
e.encode_any(u8(val[i]), level + 1, mut wr)!
} $else $if U is u16 {
e.encode_any(u16(val[i]), level + 1, mut wr)!
} $else $if U is u32 {
e.encode_any(u32(val[i]), level + 1, mut wr)!
} $else $if U is u64 {
e.encode_any(u64(val[i]), level + 1, mut wr)!
} $else $if U is $Array {
// FIXME - error: could not infer generic type `U` in call to `encode_array`
// e.encode_array(val[i], level + 1, mut wr)!
} $else $if U is $Struct {
e.encode_struct(val[i], level + 1, mut wr)!
} $else $if U is $Enum {
e.encode_any(i64(val[i]), level + 1, mut wr)!
} $else {
return error('type ${typeof(val).name} cannot be array encoded')
}
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')
}
e.encode_newline(level - 1, mut wr)!
wr.write([u8(`]`)])!
}
// str returns the JSON string representation of the `map[string]Any` type.