mirror of
https://github.com/vlang/v.git
synced 2025-09-14 06:52:36 +03:00
x.json2: add skippable field attr @[json: '-']
(improve backwards compatibility with the json
module) (#20892)
This commit is contained in:
parent
71bd94aa9e
commit
c6048d50bf
4 changed files with 322 additions and 192 deletions
|
@ -142,14 +142,20 @@ fn decode_struct[T](_ T, res map[string]Any) !T {
|
|||
mut typ := T{}
|
||||
$if T is $struct {
|
||||
$for field in T.fields {
|
||||
mut skip_field := false
|
||||
mut json_name := field.name
|
||||
|
||||
for attr in field.attrs {
|
||||
if attr.contains('json: ') {
|
||||
json_name = attr.replace('json: ', '')
|
||||
if json_name == '-' {
|
||||
skip_field = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !skip_field {
|
||||
$if field.is_enum {
|
||||
if v := res[json_name] {
|
||||
typ.$(field.name) = v.int()
|
||||
|
@ -251,6 +257,7 @@ fn decode_struct[T](_ T, res map[string]Any) !T {
|
|||
return error("The type of `${field.name}` can't be decoded. Please open an issue at https://github.com/vlang/v/issues/new/choose")
|
||||
}
|
||||
}
|
||||
}
|
||||
} $else $if T is $map {
|
||||
for k, v in res {
|
||||
// // TODO - make this work to decode types like `map[string]StructType[bool]`
|
||||
|
|
|
@ -187,19 +187,29 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut buf []u8) ! {
|
|||
}
|
||||
$for field in U.fields {
|
||||
mut ignore_field := false
|
||||
mut skip_field := false
|
||||
|
||||
value := val.$(field.name)
|
||||
|
||||
is_nil := val.$(field.name).str() == '&nil'
|
||||
|
||||
mut json_name := ''
|
||||
|
||||
for attr in field.attrs {
|
||||
if attr.contains('json: ') {
|
||||
json_name = attr.replace('json: ', '')
|
||||
if json_name == '-' {
|
||||
ignore_field = true
|
||||
skip_field = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if skip_field {
|
||||
i++
|
||||
fields_len--
|
||||
} else {
|
||||
$if value is $option {
|
||||
workaround := val.$(field.name)
|
||||
if workaround != none { // smartcast
|
||||
|
@ -237,7 +247,8 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut buf []u8) ! {
|
|||
$if field.indirections != 0 {
|
||||
if val.$(field.name) != unsafe { nil } {
|
||||
$if field.indirections == 1 {
|
||||
e.encode_value_with_level(*val.$(field.name), level + 1, mut buf)!
|
||||
e.encode_value_with_level(*val.$(field.name), level + 1, mut
|
||||
buf)!
|
||||
}
|
||||
$if field.indirections == 2 {
|
||||
e.encode_value_with_level(**val.$(field.name), level + 1, mut
|
||||
|
@ -318,6 +329,7 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut buf []u8) ! {
|
|||
return error('type ${typeof(val).name} cannot be array encoded')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if i < fields_len - 1 && !ignore_field {
|
||||
if !is_nil {
|
||||
|
|
|
@ -45,6 +45,35 @@ mut:
|
|||
val &T
|
||||
}
|
||||
|
||||
struct StructTypeSkippedFields[T] {
|
||||
mut:
|
||||
val T @[json: '-']
|
||||
val1 T
|
||||
val2 T @[json: '-']
|
||||
val3 T
|
||||
}
|
||||
|
||||
struct StructTypeSkippedFields2[T] {
|
||||
mut:
|
||||
val T
|
||||
val1 T @[json: '-']
|
||||
val2 T
|
||||
val3 T @[json: '-']
|
||||
}
|
||||
|
||||
struct StructTypeSkippedFields3[T] {
|
||||
mut:
|
||||
val T @[json: '-']
|
||||
val1 T @[json: '-']
|
||||
val2 T @[json: '-']
|
||||
val3 T @[json: '-']
|
||||
}
|
||||
|
||||
struct StructTypeSkippedField4 {
|
||||
mut:
|
||||
val map[string]string @[json: '-']
|
||||
}
|
||||
|
||||
fn test_types() {
|
||||
assert json.decode[StructType[string]]('{"val": ""}')!.val == ''
|
||||
assert json.decode[StructType[string]]('{"val": "0"}')!.val == '0'
|
||||
|
@ -126,3 +155,38 @@ fn test_types() {
|
|||
assert true
|
||||
}
|
||||
}
|
||||
|
||||
fn test_skipped_fields() {
|
||||
if x := json.decode[StructTypeSkippedFields[int]]('{"val":10,"val1":10,"val2":10,"val3":10}') {
|
||||
assert x.val == 0
|
||||
assert x.val1 == 10
|
||||
assert x.val2 == 0
|
||||
assert x.val3 == 10
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
|
||||
if x := json.decode[StructTypeSkippedFields2[int]]('{"val":10,"val1":10,"val2":10,"val3":10}') {
|
||||
assert x.val == 10
|
||||
assert x.val1 == 0
|
||||
assert x.val2 == 10
|
||||
assert x.val3 == 0
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
|
||||
if x := json.decode[StructTypeSkippedFields3[int]]('{"val":10,"val1":10,"val2":10,"val3":10}') {
|
||||
assert x.val == 0
|
||||
assert x.val1 == 0
|
||||
assert x.val2 == 0
|
||||
assert x.val3 == 0
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
|
||||
if x := json.decode[StructTypeSkippedField4]('{"val":{"a":"b"}}') {
|
||||
assert x.val.len == 0
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,30 @@ mut:
|
|||
val &T
|
||||
}
|
||||
|
||||
struct StructTypeSkippedFields[T] {
|
||||
mut:
|
||||
val T @[json: '-']
|
||||
val1 T
|
||||
val2 T @[json: '-']
|
||||
val3 T
|
||||
}
|
||||
|
||||
struct StructTypeSkippedFields2[T] {
|
||||
mut:
|
||||
val T
|
||||
val1 T @[json: '-']
|
||||
val2 T
|
||||
val3 T @[json: '-']
|
||||
}
|
||||
|
||||
struct StructTypeSkippedFields3[T] {
|
||||
mut:
|
||||
val T @[json: '-']
|
||||
val1 T @[json: '-']
|
||||
val2 T @[json: '-']
|
||||
val3 T @[json: '-']
|
||||
}
|
||||
|
||||
fn test_types() {
|
||||
assert json.encode(StructType[string]{}) == '{"val":""}'
|
||||
assert json.encode(StructType[string]{ val: '' }) == '{"val":""}'
|
||||
|
@ -211,6 +235,29 @@ fn test_option_array() {
|
|||
// }) == '{"val":[[0,1],[0,2,3],[2],[5,1]]}'
|
||||
}
|
||||
|
||||
fn test_skipped_fields() {
|
||||
assert json.encode(StructTypeSkippedFields[string]{
|
||||
val: ''
|
||||
val1: ''
|
||||
val2: ''
|
||||
val3: ''
|
||||
}) == '{"val1":"","val3":""}'
|
||||
|
||||
assert json.encode(StructTypeSkippedFields2[string]{
|
||||
val: ''
|
||||
val1: ''
|
||||
val2: ''
|
||||
val3: ''
|
||||
}) == '{"val":"","val2":""}'
|
||||
|
||||
assert json.encode(StructTypeSkippedFields3[string]{
|
||||
val: ''
|
||||
val1: ''
|
||||
val2: ''
|
||||
val3: ''
|
||||
}) == '{}'
|
||||
}
|
||||
|
||||
fn test_alias() {
|
||||
assert json.encode(StructType[StringAlias]{}) == '{"val":""}'
|
||||
assert json.encode(StructType[StringAlias]{ val: '' }) == '{"val":""}'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue