mirror of
https://github.com/netbirdio/easyjson.git
synced 2026-05-22 18:44:42 -07:00
Support json:"string" field tag.
This commit is contained in:
+24
-6
@@ -34,7 +34,21 @@ var primitiveDecoders = map[reflect.Kind]string{
|
||||
reflect.Float64: "in.Float64()",
|
||||
}
|
||||
|
||||
func (g *Generator) genTypeDecoder(t reflect.Type, out string, indent int) error {
|
||||
var primitiveStringDecoders = map[reflect.Kind]string{
|
||||
reflect.Int: "in.IntStr()",
|
||||
reflect.Int8: "in.Int8Str()",
|
||||
reflect.Int16: "in.Int16Str()",
|
||||
reflect.Int32: "in.Int32Str()",
|
||||
reflect.Int64: "in.Int64Str()",
|
||||
reflect.Uint: "in.UintStr()",
|
||||
reflect.Uint8: "in.Uint8Str()",
|
||||
reflect.Uint16: "in.Uint16Str()",
|
||||
reflect.Uint32: "in.Uint32Str()",
|
||||
reflect.Uint64: "in.Uint64Str()",
|
||||
}
|
||||
|
||||
// genTypeDecoder generates decoding code for the type t.
|
||||
func (g *Generator) genTypeDecoder(t reflect.Type, out string, tags fieldTags, indent int) error {
|
||||
ws := strings.Repeat(" ", indent)
|
||||
|
||||
unmarshalerIface := reflect.TypeOf((*easyjson.Unmarshaler)(nil)).Elem()
|
||||
@@ -52,7 +66,10 @@ func (g *Generator) genTypeDecoder(t reflect.Type, out string, indent int) error
|
||||
}
|
||||
|
||||
// Check whether type is primitive, needs to be done after interface check.
|
||||
if dec := primitiveDecoders[t.Kind()]; dec != "" {
|
||||
if dec := primitiveStringDecoders[t.Kind()]; dec != "" && tags.asString {
|
||||
fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
|
||||
return nil
|
||||
} else if dec := primitiveDecoders[t.Kind()]; dec != "" {
|
||||
fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
|
||||
return nil
|
||||
}
|
||||
@@ -76,7 +93,7 @@ func (g *Generator) genTypeDecoder(t reflect.Type, out string, indent int) error
|
||||
fmt.Fprintln(g.out, ws+"for !in.IsDelim(']') {")
|
||||
fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
|
||||
|
||||
g.genTypeDecoder(elem, tmpVar, indent+1)
|
||||
g.genTypeDecoder(elem, tmpVar, tags, indent+1)
|
||||
|
||||
fmt.Fprintln(g.out, ws+" "+out+" = append("+out+", "+tmpVar+")")
|
||||
fmt.Fprintln(g.out, ws+" in.WantComma()")
|
||||
@@ -96,7 +113,7 @@ func (g *Generator) genTypeDecoder(t reflect.Type, out string, indent int) error
|
||||
fmt.Fprintln(g.out, ws+"} else {")
|
||||
fmt.Fprintln(g.out, ws+" "+out+" = new("+g.getType(t.Elem())+")")
|
||||
|
||||
g.genTypeDecoder(t.Elem(), "*"+out, indent+1)
|
||||
g.genTypeDecoder(t.Elem(), "*"+out, tags, indent+1)
|
||||
|
||||
fmt.Fprintln(g.out, ws+"}")
|
||||
|
||||
@@ -123,7 +140,7 @@ func (g *Generator) genTypeDecoder(t reflect.Type, out string, indent int) error
|
||||
fmt.Fprintln(g.out, ws+" in.WantColon()")
|
||||
fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
|
||||
|
||||
g.genTypeDecoder(elem, tmpVar, indent+2)
|
||||
g.genTypeDecoder(elem, tmpVar, tags, indent+2)
|
||||
|
||||
fmt.Fprintln(g.out, ws+" ("+out+")[key] = "+tmpVar)
|
||||
fmt.Fprintln(g.out, ws+" in.WantComma()")
|
||||
@@ -146,9 +163,10 @@ func (g *Generator) genTypeDecoder(t reflect.Type, out string, indent int) error
|
||||
|
||||
func (g *Generator) genStructFieldDecoder(t reflect.Type, f reflect.StructField) error {
|
||||
jsonName := g.namer.GetJSONFieldName(t, f)
|
||||
tags := parseFieldTags(f)
|
||||
|
||||
fmt.Fprintf(g.out, " case %q:\n", jsonName)
|
||||
return g.genTypeDecoder(f.Type, "out."+f.Name, 3)
|
||||
return g.genTypeDecoder(f.Type, "out."+f.Name, tags, 3)
|
||||
}
|
||||
|
||||
func mergeStructFields(fields1, fields2 []reflect.StructField) (fields []reflect.StructField) {
|
||||
|
||||
+60
-23
@@ -31,7 +31,53 @@ var primitiveEncoders = map[reflect.Kind]string{
|
||||
reflect.Float64: "out.Float64(float64(%v))",
|
||||
}
|
||||
|
||||
func (g *Generator) genTypeEncoder(t reflect.Type, in string, indent int) error {
|
||||
var primitiveStringEncoders = map[reflect.Kind]string{
|
||||
reflect.Int: "out.IntStr(int(%v))",
|
||||
reflect.Int8: "out.Int8Str(int8(%v))",
|
||||
reflect.Int16: "out.Int16Str(int16(%v))",
|
||||
reflect.Int32: "out.Int32Str(int32(%v))",
|
||||
reflect.Int64: "out.Int64Str(int64(%v))",
|
||||
reflect.Uint: "out.UintStr(uint(%v))",
|
||||
reflect.Uint8: "out.Uint8Str(uint8(%v))",
|
||||
reflect.Uint16: "out.Uint16Str(uint16(%v))",
|
||||
reflect.Uint32: "out.Uint32Str(uint32(%v))",
|
||||
reflect.Uint64: "out.Uint64Str(uint64(%v))",
|
||||
}
|
||||
|
||||
// fieldTags contains parsed version of json struct field tags.
|
||||
type fieldTags struct {
|
||||
name string
|
||||
|
||||
omit bool
|
||||
omitEmpty bool
|
||||
noOmitEmpty bool
|
||||
asString bool
|
||||
}
|
||||
|
||||
// parseFieldTags parses the json field tag into a structure.
|
||||
func parseFieldTags(f reflect.StructField) fieldTags {
|
||||
var ret fieldTags
|
||||
|
||||
for i, s := range strings.Split(f.Tag.Get("json"), ",") {
|
||||
switch {
|
||||
case i == 0 && s == "-":
|
||||
ret.omit = true
|
||||
case i == 0:
|
||||
ret.name = s
|
||||
case s == "omitempty":
|
||||
ret.omitEmpty = true
|
||||
case s == "!omitempty":
|
||||
ret.noOmitEmpty = true
|
||||
case s == "string":
|
||||
ret.asString = true
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// genTypeEncoder generates code that encodes in of type t into the writer.
|
||||
func (g *Generator) genTypeEncoder(t reflect.Type, in string, tags fieldTags, indent int) error {
|
||||
ws := strings.Repeat(" ", indent)
|
||||
|
||||
marshalerIface := reflect.TypeOf((*easyjson.Marshaler)(nil)).Elem()
|
||||
@@ -47,7 +93,10 @@ func (g *Generator) genTypeEncoder(t reflect.Type, in string, indent int) error
|
||||
}
|
||||
|
||||
// Check whether type is primitive, needs to be done after interface check.
|
||||
if enc := primitiveEncoders[t.Kind()]; enc != "" {
|
||||
if enc := primitiveStringEncoders[t.Kind()]; enc != "" && tags.asString {
|
||||
fmt.Fprintf(g.out, ws+enc+"\n", in)
|
||||
return nil
|
||||
} else if enc := primitiveEncoders[t.Kind()]; enc != "" {
|
||||
fmt.Fprintf(g.out, ws+enc+"\n", in)
|
||||
return nil
|
||||
}
|
||||
@@ -64,7 +113,7 @@ func (g *Generator) genTypeEncoder(t reflect.Type, in string, indent int) error
|
||||
fmt.Fprintln(g.out, ws+" out.RawByte(',')")
|
||||
fmt.Fprintln(g.out, ws+" }")
|
||||
|
||||
g.genTypeEncoder(elem, vVar, indent+1)
|
||||
g.genTypeEncoder(elem, vVar, tags, indent+1)
|
||||
|
||||
fmt.Fprintln(g.out, ws+"}")
|
||||
fmt.Fprintln(g.out, ws+"out.RawByte(']')")
|
||||
@@ -80,7 +129,7 @@ func (g *Generator) genTypeEncoder(t reflect.Type, in string, indent int) error
|
||||
fmt.Fprintln(g.out, ws+` out.RawString("null")`)
|
||||
fmt.Fprintln(g.out, ws+"} else {")
|
||||
|
||||
g.genTypeEncoder(t.Elem(), "*"+in, indent+1)
|
||||
g.genTypeEncoder(t.Elem(), "*"+in, tags, indent+1)
|
||||
|
||||
fmt.Fprintln(g.out, ws+"}")
|
||||
|
||||
@@ -102,7 +151,7 @@ func (g *Generator) genTypeEncoder(t reflect.Type, in string, indent int) error
|
||||
fmt.Fprintln(g.out, ws+" out.String(string("+tmpVar+"_name))")
|
||||
fmt.Fprintln(g.out, ws+" out.RawByte(':')")
|
||||
|
||||
g.genTypeEncoder(t.Elem(), tmpVar+"_value", indent+2)
|
||||
g.genTypeEncoder(t.Elem(), tmpVar+"_value", tags, indent+2)
|
||||
|
||||
fmt.Fprintln(g.out, ws+" }")
|
||||
fmt.Fprintln(g.out, ws+" out.RawByte('}')")
|
||||
@@ -148,28 +197,16 @@ func (g *Generator) notEmptyCheck(t reflect.Type, v string) string {
|
||||
|
||||
func (g *Generator) genStructFieldEncoder(t reflect.Type, f reflect.StructField) error {
|
||||
jsonName := g.namer.GetJSONFieldName(t, f)
|
||||
omitEmpty := g.omitEmpty
|
||||
tags := parseFieldTags(f)
|
||||
|
||||
for i, s := range strings.Split(f.Tag.Get("json"), ",") {
|
||||
if i == 0 {
|
||||
if s == "-" {
|
||||
return nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if s == "omitempty" {
|
||||
omitEmpty = true
|
||||
} else if s == "!omitempty" {
|
||||
omitEmpty = false
|
||||
}
|
||||
if tags.omit {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !omitEmpty {
|
||||
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, 1)
|
||||
return g.genTypeEncoder(f.Type, "in."+f.Name, tags, 1)
|
||||
}
|
||||
|
||||
fmt.Fprintln(g.out, " if", g.notEmptyCheck(f.Type, "in."+f.Name), "{")
|
||||
@@ -177,7 +214,7 @@ func (g *Generator) genStructFieldEncoder(t reflect.Type, f reflect.StructField)
|
||||
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, 2); err != nil {
|
||||
if err := g.genTypeEncoder(f.Type, "in."+f.Name, tags, 2); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(g.out, " }")
|
||||
|
||||
@@ -663,6 +663,94 @@ func (r *Lexer) Int() int {
|
||||
return int(r.Int64())
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint8Str() uint8 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n uint64
|
||||
n, r.err = strconv.ParseUint(s, 10, 8)
|
||||
return uint8(n)
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint16Str() uint16 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n uint64
|
||||
n, r.err = strconv.ParseUint(s, 10, 16)
|
||||
return uint16(n)
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint32Str() uint32 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n uint64
|
||||
n, r.err = strconv.ParseUint(s, 10, 32)
|
||||
return uint32(n)
|
||||
}
|
||||
|
||||
func (r *Lexer) Uint64Str() uint64 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n uint64
|
||||
n, r.err = strconv.ParseUint(s, 10, 64)
|
||||
return n
|
||||
}
|
||||
|
||||
func (r *Lexer) UintStr() uint {
|
||||
return uint(r.Uint64Str())
|
||||
}
|
||||
|
||||
func (r *Lexer) Int8Str() int8 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n int64
|
||||
n, r.err = strconv.ParseInt(s, 10, 8)
|
||||
return int8(n)
|
||||
}
|
||||
|
||||
func (r *Lexer) Int16Str() int16 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n int64
|
||||
n, r.err = strconv.ParseInt(s, 10, 16)
|
||||
return int16(n)
|
||||
}
|
||||
|
||||
func (r *Lexer) Int32Str() int32 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n int64
|
||||
n, r.err = strconv.ParseInt(s, 10, 32)
|
||||
return int32(n)
|
||||
}
|
||||
|
||||
func (r *Lexer) Int64Str() int64 {
|
||||
s := r.UnsafeString()
|
||||
if !r.Ok() {
|
||||
return 0
|
||||
}
|
||||
var n int64
|
||||
n, r.err = strconv.ParseInt(s, 10, 64)
|
||||
return n
|
||||
}
|
||||
|
||||
func (r *Lexer) IntStr() int {
|
||||
return int(r.Int64Str())
|
||||
}
|
||||
|
||||
func (r *Lexer) Float32() float32 {
|
||||
s := r.number()
|
||||
if !r.Ok() {
|
||||
|
||||
@@ -108,6 +108,76 @@ func (w *Writer) Int64(n int64) {
|
||||
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
|
||||
}
|
||||
|
||||
func (w *Writer) Uint8Str(n uint8) {
|
||||
w.Buffer.EnsureSpace(3)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Uint16Str(n uint16) {
|
||||
w.Buffer.EnsureSpace(5)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Uint32Str(n uint32) {
|
||||
w.Buffer.EnsureSpace(10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) UintStr(n uint) {
|
||||
w.Buffer.EnsureSpace(20)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Uint64Str(n uint64) {
|
||||
w.Buffer.EnsureSpace(20)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Int8Str(n int8) {
|
||||
w.Buffer.EnsureSpace(4)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Int16Str(n int16) {
|
||||
w.Buffer.EnsureSpace(6)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Int32Str(n int32) {
|
||||
w.Buffer.EnsureSpace(11)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) IntStr(n int) {
|
||||
w.Buffer.EnsureSpace(21)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Int64Str(n int64) {
|
||||
w.Buffer.EnsureSpace(21)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Float32(n float32) {
|
||||
w.Buffer.EnsureSpace(20)
|
||||
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
|
||||
|
||||
@@ -25,6 +25,18 @@ type PrimitiveTypes struct {
|
||||
Uint32 uint32
|
||||
Uint64 uint64
|
||||
|
||||
IntString int `json:",string"`
|
||||
Int8String int8 `json:",string"`
|
||||
Int16String int16 `json:",string"`
|
||||
Int32String int32 `json:",string"`
|
||||
Int64String int64 `json:",string"`
|
||||
|
||||
UintString uint `json:",string"`
|
||||
Uint8String uint8 `json:",string"`
|
||||
Uint16String uint16 `json:",string"`
|
||||
Uint32String uint32 `json:",string"`
|
||||
Uint64String uint64 `json:",string"`
|
||||
|
||||
Float32 float32
|
||||
Float64 float64
|
||||
|
||||
@@ -49,6 +61,18 @@ var primitiveTypesValue = PrimitiveTypes{
|
||||
Uint32: math.MaxUint32,
|
||||
Uint64: math.MaxUint64,
|
||||
|
||||
IntString: math.MinInt32,
|
||||
Int8String: math.MinInt8,
|
||||
Int16String: math.MinInt16,
|
||||
Int32String: math.MinInt32,
|
||||
Int64String: math.MinInt64,
|
||||
|
||||
UintString: math.MaxUint32,
|
||||
Uint8String: math.MaxUint8,
|
||||
Uint16String: math.MaxUint16,
|
||||
Uint32String: math.MaxUint32,
|
||||
Uint64String: math.MaxUint64,
|
||||
|
||||
Float32: 1.5,
|
||||
Float64: math.MaxFloat64,
|
||||
|
||||
@@ -70,6 +94,18 @@ var primitiveTypesString = "{" +
|
||||
`"Uint32":` + fmt.Sprint(math.MaxUint32) + `,` +
|
||||
`"Uint64":` + fmt.Sprint(uint64(math.MaxUint64)) + `,` +
|
||||
|
||||
`"IntString":"` + fmt.Sprint(math.MinInt32) + `",` +
|
||||
`"Int8String":"` + fmt.Sprint(math.MinInt8) + `",` +
|
||||
`"Int16String":"` + fmt.Sprint(math.MinInt16) + `",` +
|
||||
`"Int32String":"` + fmt.Sprint(math.MinInt32) + `",` +
|
||||
`"Int64String":"` + fmt.Sprint(int64(math.MinInt64)) + `",` +
|
||||
|
||||
`"UintString":"` + fmt.Sprint(math.MaxUint32) + `",` +
|
||||
`"Uint8String":"` + fmt.Sprint(math.MaxUint8) + `",` +
|
||||
`"Uint16String":"` + fmt.Sprint(math.MaxUint16) + `",` +
|
||||
`"Uint32String":"` + fmt.Sprint(math.MaxUint32) + `",` +
|
||||
`"Uint64String":"` + fmt.Sprint(uint64(math.MaxUint64)) + `",` +
|
||||
|
||||
`"Float32":` + fmt.Sprint(1.5) + `,` +
|
||||
`"Float64":` + fmt.Sprint(math.MaxFloat64) + `,` +
|
||||
|
||||
|
||||
Reference in New Issue
Block a user