diff --git a/gen/encoder.go b/gen/encoder.go index a54f6e2..1bdb7d4 100644 --- a/gen/encoder.go +++ b/gen/encoder.go @@ -81,7 +81,7 @@ func parseFieldTags(f reflect.StructField) fieldTags { } // genTypeEncoder generates code that encodes in of type t into the writer, but uses marshaler interface if implemented by t. -func (g *Generator) genTypeEncoder(t reflect.Type, in string, tags fieldTags, indent int) error { +func (g *Generator) genTypeEncoder(t reflect.Type, in string, tags fieldTags, indent int, assumeNonEmpty bool) error { ws := strings.Repeat(" ", indent) marshalerIface := reflect.TypeOf((*easyjson.Marshaler)(nil)).Elem() @@ -102,12 +102,12 @@ func (g *Generator) genTypeEncoder(t reflect.Type, in string, tags fieldTags, in return nil } - err := g.genTypeEncoderNoCheck(t, in, tags, indent) + err := g.genTypeEncoderNoCheck(t, in, tags, indent, assumeNonEmpty) return err } // genTypeEncoderNoCheck generates code that encodes in of type t into the writer. -func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldTags, indent int) error { +func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldTags, indent int, assumeNonEmpty bool) error { ws := strings.Repeat(" ", indent) // Check whether type is primitive, needs to be done after interface check. @@ -128,16 +128,20 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT if t.Elem().Kind() == reflect.Uint8 { fmt.Fprintln(g.out, ws+"out.Base64Bytes("+in+")") } else { - fmt.Fprintln(g.out, ws+"if "+in+" == nil && (out.Flags & jwriter.NilSliceAsEmpty) == 0 {") - fmt.Fprintln(g.out, ws+` out.RawString("null")`) - fmt.Fprintln(g.out, ws+"} else {") + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"if "+in+" == nil && (out.Flags & jwriter.NilSliceAsEmpty) == 0 {") + fmt.Fprintln(g.out, ws+` out.RawString("null")`) + fmt.Fprintln(g.out, ws+"} else {") + } else { + fmt.Fprintln(g.out, ws+"{") + } fmt.Fprintln(g.out, ws+" out.RawByte('[')") fmt.Fprintln(g.out, ws+" for "+iVar+", "+vVar+" := range "+in+" {") fmt.Fprintln(g.out, ws+" if "+iVar+" > 0 {") fmt.Fprintln(g.out, ws+" out.RawByte(',')") fmt.Fprintln(g.out, ws+" }") - g.genTypeEncoder(elem, vVar, tags, indent+2) + g.genTypeEncoder(elem, vVar, tags, indent+2, false) fmt.Fprintln(g.out, ws+" }") fmt.Fprintln(g.out, ws+" out.RawByte(']')") @@ -157,7 +161,7 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT fmt.Fprintln(g.out, ws+" out.RawByte(',')") fmt.Fprintln(g.out, ws+" }") - g.genTypeEncoder(elem, in+"["+iVar+"]", tags, indent+1) + g.genTypeEncoder(elem, in+"["+iVar+"]", tags, indent+1, false) fmt.Fprintln(g.out, ws+"}") fmt.Fprintln(g.out, ws+"out.RawByte(']')") @@ -170,13 +174,17 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT fmt.Fprintln(g.out, ws+enc+"(out, "+in+")") case reflect.Ptr: - fmt.Fprintln(g.out, ws+"if "+in+" == nil {") - fmt.Fprintln(g.out, ws+` out.RawString("null")`) - fmt.Fprintln(g.out, ws+"} else {") + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"if "+in+" == nil {") + fmt.Fprintln(g.out, ws+` out.RawString("null")`) + fmt.Fprintln(g.out, ws+"} else {") + } - g.genTypeEncoder(t.Elem(), "*"+in, tags, indent+1) + g.genTypeEncoder(t.Elem(), "*"+in, tags, indent+1, false) - fmt.Fprintln(g.out, ws+"}") + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"}") + } case reflect.Map: key := t.Key() @@ -185,18 +193,21 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT } tmpVar := g.uniqueVarName() - fmt.Fprintln(g.out, ws+"if "+in+" == nil && (out.Flags & jwriter.NilMapAsEmpty) == 0 {") - fmt.Fprintln(g.out, ws+" out.RawString(`null`)") - fmt.Fprintln(g.out, ws+"} else {") + if !assumeNonEmpty { + fmt.Fprintln(g.out, ws+"if "+in+" == nil && (out.Flags & jwriter.NilMapAsEmpty) == 0 {") + fmt.Fprintln(g.out, ws+" out.RawString(`null`)") + fmt.Fprintln(g.out, ws+"} else {") + } else { + fmt.Fprintln(g.out, ws+"{") + } 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+" if "+tmpVar+"First { "+tmpVar+"First = false } else { out.RawByte(',') }") fmt.Fprintln(g.out, ws+" out.String(string("+tmpVar+"Name))") fmt.Fprintln(g.out, ws+" out.RawByte(':')") - g.genTypeEncoder(t.Elem(), tmpVar+"Value", tags, indent+2) + g.genTypeEncoder(t.Elem(), tmpVar+"Value", tags, indent+2, false) fmt.Fprintln(g.out, ws+" }") fmt.Fprintln(g.out, ws+" out.RawByte('}')") @@ -255,18 +266,23 @@ func (g *Generator) genStructFieldEncoder(t reflect.Type, f reflect.StructField) return nil } if !tags.omitEmpty && !g.omitEmpty || tags.noOmitEmpty { - fmt.Fprintln(g.out, " if !first { out.RawByte(',') }") - fmt.Fprintln(g.out, " first = false") - fmt.Fprintf(g.out, " out.RawString(%q)\n", strconv.Quote(jsonName)+":") - return g.genTypeEncoder(f.Type, "in."+f.Name, tags, 1) + fmt.Fprintln(g.out, " if first {") + fmt.Fprintln(g.out, " first = false") + fmt.Fprintf(g.out, " out.RawString(%q)\n", strconv.Quote(jsonName)+":") + fmt.Fprintln(g.out, " } else {") + fmt.Fprintf(g.out, " out.RawString(%q)\n", ","+strconv.Quote(jsonName)+":") + fmt.Fprintln(g.out, " }") + return g.genTypeEncoder(f.Type, "in."+f.Name, tags, 1, false) } fmt.Fprintln(g.out, " if", g.notEmptyCheck(f.Type, "in."+f.Name), "{") - fmt.Fprintln(g.out, " if !first { out.RawByte(',') }") - fmt.Fprintln(g.out, " first = false") - - fmt.Fprintf(g.out, " out.RawString(%q)\n", strconv.Quote(jsonName)+":") - if err := g.genTypeEncoder(f.Type, "in."+f.Name, tags, 2); err != nil { + fmt.Fprintln(g.out, " if first {") + fmt.Fprintln(g.out, " first = false") + fmt.Fprintf(g.out, " out.RawString(%q)\n", strconv.Quote(jsonName)+":") + fmt.Fprintln(g.out, " } else {") + fmt.Fprintf(g.out, " out.RawString(%q)\n", ","+strconv.Quote(jsonName)+":") + fmt.Fprintln(g.out, " }") + if err := g.genTypeEncoder(f.Type, "in."+f.Name, tags, 2, true); err != nil { return err } fmt.Fprintln(g.out, " }") @@ -293,7 +309,7 @@ func (g *Generator) genSliceArrayMapEncoder(t reflect.Type) error { typ := g.getType(t) fmt.Fprintln(g.out, "func "+fname+"(out *jwriter.Writer, in "+typ+") {") - err := g.genTypeEncoderNoCheck(t, "in", fieldTags{}, 1) + err := g.genTypeEncoderNoCheck(t, "in", fieldTags{}, 1, false) if err != nil { return err }