mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
x.json2, toml: add support for Any
in decode_struct
, encode_struct
and to_any
(#21972)
This commit is contained in:
parent
28103d15d5
commit
2d43f38bf3
@ -34,6 +34,10 @@ struct Contact {
|
||||
phone string
|
||||
}*/
|
||||
|
||||
struct AnyStruct {
|
||||
val toml.Any
|
||||
}
|
||||
|
||||
struct Employee {
|
||||
mut:
|
||||
name string
|
||||
@ -56,6 +60,11 @@ struct Arrs {
|
||||
times []toml.Time
|
||||
}
|
||||
|
||||
// individual because toml.decode[Foo](str)! == foo is false
|
||||
struct AnyArr {
|
||||
arr []toml.Any
|
||||
}
|
||||
|
||||
fn test_encode_and_decode() {
|
||||
// *¹
|
||||
// p := Pet{'Mr. Scratchy McEvilPaws', ['Freddy', 'Fred', 'Charles'], 8, -1, 0.8, true, .manager, Address{'1428 Elm Street', 'Springwood'}, Contact{'123-456-7890'}}
|
||||
@ -82,6 +91,14 @@ meal_frequency = { bones = 2, kibble = 5 }'
|
||||
assert toml.decode[Pet](s)! == p
|
||||
}
|
||||
|
||||
fn test_encode_and_decode_any() {
|
||||
a := AnyStruct{toml.Any(10)}
|
||||
s := 'val = 10'
|
||||
|
||||
assert toml.encode[AnyStruct](a) == s
|
||||
assert toml.decode[AnyStruct](s)!.val.int() == 10
|
||||
}
|
||||
|
||||
pub fn (e Employee) to_toml() string {
|
||||
mut mp := map[string]toml.Any{}
|
||||
mp['name'] = toml.Any(e.name)
|
||||
@ -250,6 +267,16 @@ times = [
|
||||
|
||||
assert toml.encode[Arrs](a) == s
|
||||
assert toml.decode[Arrs](s)! == a
|
||||
|
||||
any_a := AnyArr{[toml.Any(10), 20, 30]}
|
||||
any_s := 'arr = [
|
||||
10,
|
||||
20,
|
||||
30
|
||||
]'
|
||||
|
||||
assert toml.encode[AnyArr](any_a) == any_s
|
||||
assert toml.decode[AnyArr](any_s)!.arr.map(it.int()) == [10, 20, 30]
|
||||
}
|
||||
|
||||
fn test_decode_doc() {
|
||||
|
@ -68,6 +68,8 @@ fn decode_struct[T](doc Any, mut typ T) {
|
||||
typ.$(field.name) = value.date()
|
||||
} $else $if field.typ is Time {
|
||||
typ.$(field.name) = value.time()
|
||||
} $else $if field.typ is Any {
|
||||
typ.$(field.name) = value
|
||||
} $else $if field.is_array {
|
||||
arr := value.array()
|
||||
match field.typ {
|
||||
@ -81,6 +83,7 @@ fn decode_struct[T](doc Any, mut typ T) {
|
||||
[]DateTime { typ.$(field.name) = arr.map(it.datetime()) }
|
||||
[]Date { typ.$(field.name) = arr.map(it.date()) }
|
||||
[]Time { typ.$(field.name) = arr.map(it.time()) }
|
||||
[]Any { typ.$(field.name) = arr }
|
||||
else {}
|
||||
}
|
||||
} $else $if field.is_map {
|
||||
@ -146,6 +149,9 @@ fn decode_struct[T](doc Any, mut typ T) {
|
||||
return k, v.time()
|
||||
})
|
||||
}
|
||||
map[string]Any {
|
||||
typ.$(field.name) = mmap.clone()
|
||||
}
|
||||
else {}
|
||||
}
|
||||
} $else $if field.is_struct {
|
||||
@ -211,6 +217,8 @@ fn to_any[T](value T) Any {
|
||||
return Any(value)
|
||||
} $else $if T is DateTime {
|
||||
return Any(value)
|
||||
} $else $if T is Any {
|
||||
return value
|
||||
} $else $if T is $struct {
|
||||
$for method in T.methods {
|
||||
$if method.name == 'to_toml' {
|
||||
|
@ -267,6 +267,12 @@ fn decode_struct[T](_ T, res map[string]Any) !T {
|
||||
if json_name in res {
|
||||
typ.$(field.name) = res[json_name]!.to_time()!
|
||||
}
|
||||
} $else $if field.typ is Any {
|
||||
typ.$(field.name) = res[json_name]!
|
||||
} $else $if field.typ is ?Any {
|
||||
if json_name in res {
|
||||
typ.$(field.name) = res[json_name]!
|
||||
}
|
||||
} $else $if field.is_array {
|
||||
arr := res[field.name]! as []Any
|
||||
// vfmt off
|
||||
@ -292,6 +298,8 @@ fn decode_struct[T](_ T, res map[string]Any) !T {
|
||||
// NOTE: Using `!` on `to_time()` inside the array method causes a builder error - 2024/04/01.
|
||||
[]time.Time { typ.$(field.name) = arr.map(it.to_time() or { time.Time{} }) }
|
||||
[]?time.Time { typ.$(field.name) = arr.map(?time.Time(it.to_time() or { time.Time{} })) }
|
||||
[]Any { typ.$(field.name) = arr }
|
||||
[]?Any { typ.$(field.name) = arr.map(?Any(it)) }
|
||||
[]u8 { typ.$(field.name) = arr.map(it.u64()) }
|
||||
[]?u8 { typ.$(field.name) = arr.map(?u8(it.u64())) }
|
||||
[]u16 { typ.$(field.name) = arr.map(it.u64()) }
|
||||
|
28
vlib/x/json2/tests/decode_and_encode_struct_any_test.v
Normal file
28
vlib/x/json2/tests/decode_and_encode_struct_any_test.v
Normal file
@ -0,0 +1,28 @@
|
||||
import x.json2 as json
|
||||
|
||||
struct AnyStruct[T] {
|
||||
val T
|
||||
}
|
||||
|
||||
struct OptAnyStruct[T] {
|
||||
val ?T
|
||||
}
|
||||
|
||||
/*struct OptAnyArrStruct {
|
||||
val []?json.Any
|
||||
}*/
|
||||
|
||||
fn test_values() {
|
||||
assert json.decode[AnyStruct[json.Any]]('{"val":5}')!.val.int() == 5
|
||||
assert json.decode[OptAnyStruct[json.Any]]('{}')!.val == none
|
||||
assert json.decode[AnyStruct[[]json.Any]]('{"val":[5,10]}')!.val.map(it.int()) == [
|
||||
5,
|
||||
10,
|
||||
]
|
||||
// assert json.decode[OptAnyArrStruct]('{"val":[5,null,10]}')!.val == [?json.Any(5),json.Null{},10] skipped because test still fails even though they're the same
|
||||
|
||||
assert json.encode[AnyStruct[json.Any]](AnyStruct[json.Any]{json.Any(5)}) == '{"val":5}'
|
||||
assert json.encode[OptAnyStruct[json.Any]](OptAnyStruct[json.Any]{none}) == '{}'
|
||||
assert json.encode[AnyStruct[[]json.Any]](AnyStruct[[]json.Any]{[json.Any(5), 10]}) == '{"val":[5,10]}'
|
||||
// assert json.encode[OptAnyArrStruct](OptAnyArrStruct{[?json.Any(5),none,10]}) == '{"val":[5,null,10]}' encode_array has not implemented optional arrays yet
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user