From b0589c645dc6ba3a1852f03cfc2080b2e7cf2c3c Mon Sep 17 00:00:00 2001 From: Hitalo Souza <63821277+enghitalo@users.noreply.github.com> Date: Fri, 28 Apr 2023 10:24:27 -0300 Subject: [PATCH] json2: encode reference fields too (#17058) --- vlib/x/json2/encode_struct_test.v | 20 +++++++++++++++ vlib/x/json2/encode_struct_todo_test.vv | 20 --------------- vlib/x/json2/encoder.v | 25 ++++++++++++++++--- vlib/x/json2/json2.v | 4 +-- .../json_test.v | 19 ++++++++++++++ .../json_todo_test.vv | 18 ------------- 6 files changed, 63 insertions(+), 43 deletions(-) diff --git a/vlib/x/json2/encode_struct_test.v b/vlib/x/json2/encode_struct_test.v index 68350c723f..7bfc5553cd 100644 --- a/vlib/x/json2/encode_struct_test.v +++ b/vlib/x/json2/encode_struct_test.v @@ -227,6 +227,26 @@ fn test_alias() { assert json.encode(StructType[StructAlias]{ val: StructType[int]{1} }) == '{"val":{"val":1}}' } +fn test_pointer() { + mut string_initialized_with_reference := '' + assert json.encode(StructTypePointer[string]{ val: 0 }) == '{}' + assert json.encode(StructTypePointer[string]{ val: &string_initialized_with_reference }) == '{"val":""}' + string_initialized_with_reference = 'a' + assert json.encode(StructTypePointer[string]{ val: &string_initialized_with_reference }) == '{"val":"a"}' + + mut bool_initialized_with_reference := false + assert json.encode(StructTypePointer[bool]{ val: 0 }) == '{}' + assert json.encode(StructTypePointer[bool]{ val: &bool_initialized_with_reference }) == '{"val":false}' + bool_initialized_with_reference = true + assert json.encode(StructTypePointer[bool]{ val: &bool_initialized_with_reference }) == '{"val":true}' + + mut int_initialized_with_reference := 0 + assert json.encode(StructTypePointer[int]{ val: 0 }) == '{}' + assert json.encode(StructTypePointer[int]{ val: &int_initialized_with_reference }) == '{"val":0}' + int_initialized_with_reference = 1 + assert json.encode(StructTypePointer[int]{ val: &int_initialized_with_reference }) == '{"val":1}' +} + fn test_sumtypes() { assert json.encode(StructType[SumTypes]{}) == '{}' assert json.encode(StructType[SumTypes]{ val: '' }) == '{"val":""}' diff --git a/vlib/x/json2/encode_struct_todo_test.vv b/vlib/x/json2/encode_struct_todo_test.vv index 5106723dfb..9f4d53f2f8 100644 --- a/vlib/x/json2/encode_struct_todo_test.vv +++ b/vlib/x/json2/encode_struct_todo_test.vv @@ -108,26 +108,6 @@ fn test_option_sumtypes() { assert json.encode(StructTypeOption[SumTypes]{ val: 1 }) == '{"val":1}' } -fn test_pointer() { - // mut string_initialized_with_reference := "" - assert json.encode(StructTypePointer[string]{ val: 0 }) == '{"val":""}' // REVIEW - assert json.encode(StructTypePointer[string]{ val: &string_initialized_with_reference }) == '{"val":""}' - string_initialized_with_reference = 'a' - assert json.encode(StructTypePointer[string]{ val: &string_initialized_with_reference }) == '{"val":"a"}' - - mut bool_initialized_with_reference := false - assert json.encode(StructTypePointer[bool]{ val: 0 }) == '{"val":false}' // REVIEW - assert json.encode(StructTypePointer[bool]{ val: &bool_initialized_with_reference }) == '{"val":false}' - bool_initialized_with_reference = true - assert json.encode(StructTypePointer[bool]{ val: &bool_initialized_with_reference }) == '{"val":true}' - - mut int_initialized_with_reference := 0 - assert json.encode(StructTypePointer[int]{ val: 0 }) == '{"val":0}' // REVIEW - assert json.encode(StructTypePointer[int]{ val: &int_initialized_with_reference }) == '{"val":0}' - int_initialized_with_reference = 1 - assert json.encode(StructTypePointer[int]{ val: &int_initialized_with_reference }) == '{"val":1}' -} - fn test_caos() { typed_string_struct := StructType[string]{ val: 'a' diff --git a/vlib/x/json2/encoder.v b/vlib/x/json2/encoder.v index 4014c181a9..286f9014ab 100644 --- a/vlib/x/json2/encoder.v +++ b/vlib/x/json2/encoder.v @@ -182,6 +182,9 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! { $for field in U.fields { mut ignore_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: ') { @@ -251,7 +254,7 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! { } } $else { is_none := val.$(field.name).str() == 'unknown sum type value' - if !is_none { + if !is_none && !is_nil { e.encode_newline(level, mut wr)! if json_name != '' { e.encode_string(json_name, mut wr)! @@ -265,7 +268,21 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! { } } - $if field.typ is string { + $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 wr)! + } + $if field.indirections == 2 { + e.encode_value_with_level(**val.$(field.name), level + 1, mut + wr)! + } + $if field.indirections == 3 { + e.encode_value_with_level(***val.$(field.name), level + 1, mut + wr)! + } + } + } $else $if field.typ is string { e.encode_string(val.$(field.name).str(), mut wr)! } $else $if field.typ is time.Time { wr.write(json2.quote_bytes)! @@ -377,7 +394,9 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! { } if i < fields_len - 1 && !ignore_field { - wr.write(json2.comma_bytes)! + if !is_nil { + wr.write(json2.comma_bytes)! + } } if !ignore_field { i++ diff --git a/vlib/x/json2/json2.v b/vlib/x/json2/json2.v index ef7838dfa8..c035160d2c 100644 --- a/vlib/x/json2/json2.v +++ b/vlib/x/json2/json2.v @@ -162,7 +162,7 @@ pub fn encode[T](val T) string { } default_encoder.encode_value(val, mut sb) or { - dump(err) + println(err) default_encoder.encode_value[Null](null, mut sb) or {} } @@ -179,7 +179,7 @@ fn encode_array[T](val []T) string { } default_encoder.encode_array(val, 1, mut sb) or { - dump(err) + println(err) default_encoder.encode_value[Null](null, mut sb) or {} } diff --git a/vlib/x/json2/json_module_compatibility_test/json_test.v b/vlib/x/json2/json_module_compatibility_test/json_test.v index 7a455afdf4..b26a101993 100644 --- a/vlib/x/json2/json_module_compatibility_test/json_test.v +++ b/vlib/x/json2/json_module_compatibility_test/json_test.v @@ -265,6 +265,25 @@ fn test_encode_alias_field() { assert s == '{"sub":{"a":1}}' } +struct APrice {} + +pub struct Association { + association &Association = unsafe { nil } + price APrice +} + +//! FIX: returning null +fn test_encoding_struct_with_pointers() { + value := Association{ + association: &Association{ + price: APrice{} + } + price: APrice{} + } + // println(value) + assert json.encode(value) == '{"association":{"price":{}},"price":{}}' +} + pub struct City { mut: name string diff --git a/vlib/x/json2/json_module_compatibility_test/json_todo_test.vv b/vlib/x/json2/json_module_compatibility_test/json_todo_test.vv index 8fd258222a..a4f641c9d2 100644 --- a/vlib/x/json2/json_module_compatibility_test/json_todo_test.vv +++ b/vlib/x/json2/json_module_compatibility_test/json_todo_test.vv @@ -367,21 +367,3 @@ fn test_encode_sumtype_defined_ahead() { ret := create_game_packet(&GamePacketData(GPScale{})) assert ret == '{"value":0,"_type":"GPScale"}' } - -struct APrice {} - -struct Association { - association &Association = unsafe { nil } - price APrice -} - -//! FIX: returning null -fn test_encoding_struct_with_pointers() { - value := Association{ - association: &Association{ - price: APrice{} - } - price: APrice{} - } - assert json.encode(value) == '{"association":{"price":{}},"price":{}}' -}