diff --git a/gen/decoder.go b/gen/decoder.go index c01ea38..ea38f2b 100644 --- a/gen/decoder.go +++ b/gen/decoder.go @@ -108,25 +108,29 @@ func (g *Generator) genTypeDecoder(t reflect.Type, out string, indent int) error elem := t.Elem() tmpVar := g.uniqueVarName() - fmt.Fprintln(g.out, ws+"in.Delim('{')") - fmt.Fprintln(g.out, ws+"if !in.IsDelim('}') {") - fmt.Fprintln(g.out, ws+out+" = make("+g.getType(t)+")") + fmt.Fprintln(g.out, ws+"if in.IsNull() {") + fmt.Fprintln(g.out, ws+" in.Skip()") fmt.Fprintln(g.out, ws+"} else {") - fmt.Fprintln(g.out, ws+out+" = nil") + fmt.Fprintln(g.out, ws+" in.Delim('{')") + fmt.Fprintln(g.out, ws+" if !in.IsDelim('}') {") + fmt.Fprintln(g.out, ws+" "+out+" = make("+g.getType(t)+")") + fmt.Fprintln(g.out, ws+" } else {") + fmt.Fprintln(g.out, ws+" "+out+" = nil") + fmt.Fprintln(g.out, ws+" }") + + fmt.Fprintln(g.out, ws+" for !in.IsDelim('}') {") + fmt.Fprintln(g.out, ws+" key := in.String()") + fmt.Fprintln(g.out, ws+" in.WantColon()") + fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem)) + + g.genTypeDecoder(elem, tmpVar, indent+2) + + fmt.Fprintln(g.out, ws+" ("+out+")[key] = "+tmpVar) + fmt.Fprintln(g.out, ws+" in.WantComma()") + fmt.Fprintln(g.out, ws+" }") + fmt.Fprintln(g.out, ws+" in.Delim('}')") fmt.Fprintln(g.out, ws+"}") - fmt.Fprintln(g.out, ws+"for !in.IsDelim('}') {") - fmt.Fprintln(g.out, ws+" key := in.String()") - fmt.Fprintln(g.out, ws+" in.WantColon()") - fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem)) - - g.genTypeDecoder(elem, tmpVar, indent+1) - - fmt.Fprintln(g.out, ws+" ("+out+")[key] = "+tmpVar) - fmt.Fprintln(g.out, ws+" in.WantComma()") - fmt.Fprintln(g.out, ws+"}") - fmt.Fprintln(g.out, ws+"in.Delim('}')") - case reflect.Interface: if t.NumMethod() != 0 { return fmt.Errorf("interface type %v not supported: only interface{} is allowed", t) diff --git a/gen/encoder.go b/gen/encoder.go index 6228130..d55a4a6 100644 --- a/gen/encoder.go +++ b/gen/encoder.go @@ -91,17 +91,22 @@ func (g *Generator) genTypeEncoder(t reflect.Type, in string, indent int) error } tmpVar := g.uniqueVarName() - fmt.Fprintln(g.out, ws+"out.RawByte('{')") - fmt.Fprintln(g.out, ws+tmpVar+"_first := true") - fmt.Fprintln(g.out, ws+"for "+tmpVar+"_name, "+tmpVar+"_value := range "+in+" {") - fmt.Fprintln(g.out, ws+" if !"+tmpVar+"_first { out.RawByte(',') }") - fmt.Fprintln(g.out, ws+" "+tmpVar+"_first = false") - fmt.Fprintln(g.out, ws+" out.String("+tmpVar+"_name)") + fmt.Fprintln(g.out, ws+"if "+in+" == nil {") + fmt.Fprintln(g.out, ws+" out.RawString(`null`)") + fmt.Fprintln(g.out, ws+"} else {") + fmt.Fprintln(g.out, ws+" out.RawByte('{')") + fmt.Fprintln(g.out, ws+" "+tmpVar+"_first := true") + fmt.Fprintln(g.out, ws+" for "+tmpVar+"_name, "+tmpVar+"_value := range "+in+" {") + fmt.Fprintln(g.out, ws+" if !"+tmpVar+"_first { out.RawByte(',') }") + fmt.Fprintln(g.out, ws+" "+tmpVar+"_first = false") + fmt.Fprintln(g.out, ws+" out.String("+tmpVar+"_name)") + fmt.Fprintln(g.out, ws+" out.RawByte(':')") - g.genTypeEncoder(t.Elem(), tmpVar+"_value", indent+1) + g.genTypeEncoder(t.Elem(), tmpVar+"_value", indent+2) + fmt.Fprintln(g.out, ws+" }") + fmt.Fprintln(g.out, ws+" out.RawByte('}')") fmt.Fprintln(g.out, ws+"}") - fmt.Fprintln(g.out, ws+"out.RawByte('}')") case reflect.Interface: if t.NumMethod() != 0 { diff --git a/tests/basic_test.go b/tests/basic_test.go index 075f148..4231eea 100644 --- a/tests/basic_test.go +++ b/tests/basic_test.go @@ -29,6 +29,7 @@ var testCases = []struct { {&stdMarshalerValue, stdMarshalerString}, {&unexportedStructValue, unexportedStructString}, {&excludedFieldValue, excludedFieldString}, + {&mapsValue, mapsString}, } func TestMarshal(t *testing.T) { @@ -56,7 +57,7 @@ func TestUnmarshal(t *testing.T) { } if !reflect.DeepEqual(v, test.Decoded) { - t.Errorf("[%d, %T] UnmarshalJSON(): got \n%+v\n\t\t want \n%+v", i, test.Decoded, v, test.Encoded) + t.Errorf("[%d, %T] UnmarshalJSON(): got \n%+v\n\t\t want \n%+v", i, test.Decoded, v, test.Decoded) } } } diff --git a/tests/data.go b/tests/data.go index 9f1ef81..f284720 100644 --- a/tests/data.go +++ b/tests/data.go @@ -373,3 +373,20 @@ var excludedFieldValue = ExcludedField{ DoNotProcess: false, } var excludedFieldString = `{"process":true}` + +type Maps struct { + Map map[string]string + InterfaceMap map[string]interface{} + NilMap map[string]string +} + +var mapsValue = Maps{ + Map: map[string]string{"A": "b"}, // only one item since map iteration is randomized + InterfaceMap: map[string]interface{}{"G": 1}, +} + +var mapsString = `{` + + `"Map":{"A":"b"},` + + `"InterfaceMap":{"G":1},` + + `"NilMap":null` + + `}`