From 0ac6ba9354e7eb3ba2356d8bb6d34d8ff6f1cf82 Mon Sep 17 00:00:00 2001 From: Hitalo Souza <63821277+enghitalo@users.noreply.github.com> Date: Sat, 21 Jan 2023 15:26:55 -0300 Subject: [PATCH] json2: encode sumtype (#17041) --- vlib/x/json2/encode_struct_test.v | 32 +++++++++- vlib/x/json2/encoder.v | 103 ++++++++++++++++++++---------- 2 files changed, 102 insertions(+), 33 deletions(-) diff --git a/vlib/x/json2/encode_struct_test.v b/vlib/x/json2/encode_struct_test.v index e13c2111b7..3aaabcdd02 100644 --- a/vlib/x/json2/encode_struct_test.v +++ b/vlib/x/json2/encode_struct_test.v @@ -18,7 +18,7 @@ type TimeAlias = time.Time type StructAlias = StructType[int] type EnumAlias = Enumerates -type SumTypes = bool | int | string +type SumTypes = StructType[string] | bool | int | string | time.Time enum Enumerates { a @@ -222,3 +222,33 @@ fn test_alias() { assert json.encode(StructType[StructAlias]{ val: StructType[int]{0} }) == '{"val":{"val":0}}' assert json.encode(StructType[StructAlias]{ val: StructType[int]{1} }) == '{"val":{"val":1}}' } + +fn test_sumtypes() { + assert json.encode(StructType[SumTypes]{}) == '{}' + assert json.encode(StructType[SumTypes]{ val: '' }) == '{"val":""}' + assert json.encode(StructType[SumTypes]{ val: 'a' }) == '{"val":"a"}' + + assert json.encode(StructType[SumTypes]{ val: false }) == '{"val":false}' + assert json.encode(StructType[SumTypes]{ val: true }) == '{"val":true}' + + assert json.encode(StructType[SumTypes]{ val: 0 }) == '{"val":0}' + assert json.encode(StructType[SumTypes]{ val: 1 }) == '{"val":1}' + + assert json.encode(StructType[SumTypes]{ val: fixed_time }) == '{"val":2022-03-11T13:54:25.000Z}' + + assert json.encode(StructType[StructType[SumTypes]]{ + val: StructType[SumTypes]{ + val: 1 + } + }) == '{"val":{"val":1}}' + + // assert json.encode(StructType[SumTypes]{ val: StructType[string]{ + // val: '111111' + // } }) == '{"val":1}' + + assert json.encode(StructType[StructType[SumTypes]]{ + val: StructType[SumTypes]{ + val: 1 + } + }) == '{"val":{"val":1}}' +} diff --git a/vlib/x/json2/encoder.v b/vlib/x/json2/encoder.v index 273de3852c..98df0e41b8 100644 --- a/vlib/x/json2/encoder.v +++ b/vlib/x/json2/encoder.v @@ -221,16 +221,19 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! { } } } $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)! + is_none := val.$(field.name).str() == 'unknown sum type value' + 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)! + } + wr.write(json2.colon_bytes)! - if e.newline != 0 { - wr.write(json2.space_bytes)! + if e.newline != 0 { + wr.write(json2.space_bytes)! + } } $if field.typ is string { @@ -254,29 +257,65 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! { } $else $if field.typ is $Enum { // wr.write(int(val.$(field.name)).str().bytes())! // FIXME - error: cannot cast string to `int`, use `val.$field.name.int()` instead. } $else $if field.typ is $Sumtype { - // // FIXME - error: cannot match `bool` with `string` - // match value { - // string { - // println(val.$(field.name)) - // } - // bool { - // } - // i8, i16, int, i64 { - // } - // u8, u16, u32, u64 { - // } - // f32, f64 { - // } - // map[string]Any { - // } - // []Any { - // } - // time.Time {} - // Null { - // } else { - // dump("elsa") - // } - // } + // dump(val.$(field.name).str()) + // dump(is_none) + sum_type_value := value.str()#[typeof(val.$(field.name)).name.len + 1..-1] + + is_string := sum_type_value[0] == "'"[0] + + // mut is_struct := false + // mut is_sumtype := false + // mut is_enum := false + // mut is_array := false + + match sum_type_value[0] { + `0`...`9` { + if sum_type_value.contains_any(' /:-') { + date_time_str := time.parse(sum_type_value)! + wr.write(date_time_str.format_rfc3339().bytes())! + } else { + wr.write(sum_type_value.bytes())! + } + } + `A`...`Z` { + // SumTypes(0) + if sum_type_value.contains('(') { + if !sum_type_value.all_before('(').contains_any(' "\'[') { + // is_sumtype = true + } + } + // StructType{ + // StructType[int]{ + if sum_type_value.contains('{') { + if !sum_type_value.all_before('{').contains_any(' "\'') { + // is_struct = true + // TODO + // e.encode_struct_from_sumtype(value, level + 1, mut wr)! + } + } + } + `a`...`z` { + if sum_type_value in ['true', 'false'] { + wr.write(sum_type_value.bytes())! + } else { + // is_enum = true + } + } + else { + // dump('else') + } + } + // dump(sum_type_value) + + // dump(is_none) + // dump(is_string) + // dump(is_struct) + // dump(is_sumtype) + // dump(is_enum) + // dump(is_array) + if is_string { + e.encode_string(sum_type_value#[1..-1], mut wr)! + } } $else $if field.typ is $Alias { $if field.unaliased_typ is string { e.encode_string(val.$(field.name).str(), mut wr)!