mirror of
https://github.com/netbirdio/easyjson.git
synced 2026-05-22 18:44:42 -07:00
Merge pull request #147 from ChuntaoLu/lu.int
Support maps with key types that are integers
This commit is contained in:
@@ -12,6 +12,7 @@ root: .root/src/$(PKG)
|
||||
|
||||
clean:
|
||||
rm -rf .root
|
||||
rm -rf tests/*_easyjson.go
|
||||
|
||||
build:
|
||||
go build -i -o .root/bin/easyjson $(PKG)/easyjson
|
||||
|
||||
+16
-13
@@ -36,16 +36,18 @@ var primitiveDecoders = map[reflect.Kind]string{
|
||||
}
|
||||
|
||||
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()",
|
||||
reflect.String: "in.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()",
|
||||
reflect.Uintptr: "in.UintptrStr()",
|
||||
}
|
||||
|
||||
var customDecoders = map[string]string{
|
||||
@@ -205,8 +207,9 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field
|
||||
|
||||
case reflect.Map:
|
||||
key := t.Key()
|
||||
if key.Kind() != reflect.String {
|
||||
return fmt.Errorf("map type %v not supported: only string keys are allowed", key)
|
||||
keyDec, ok := primitiveStringDecoders[key.Kind()]
|
||||
if !ok {
|
||||
return fmt.Errorf("map type %v not supported: only string and integer keys are allowed", key)
|
||||
}
|
||||
elem := t.Elem()
|
||||
tmpVar := g.uniqueVarName()
|
||||
@@ -222,7 +225,7 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field
|
||||
fmt.Fprintln(g.out, ws+" }")
|
||||
|
||||
fmt.Fprintln(g.out, ws+" for !in.IsDelim('}') {")
|
||||
fmt.Fprintln(g.out, ws+" key := "+g.getType(t.Key())+"(in.String())")
|
||||
fmt.Fprintln(g.out, ws+" key := "+g.getType(key)+"("+keyDec+")")
|
||||
fmt.Fprintln(g.out, ws+" in.WantColon()")
|
||||
fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
|
||||
|
||||
|
||||
+16
-13
@@ -33,16 +33,18 @@ var primitiveEncoders = map[reflect.Kind]string{
|
||||
}
|
||||
|
||||
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))",
|
||||
reflect.String: "out.String(string(%v))",
|
||||
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))",
|
||||
reflect.Uintptr: "out.UintptrStr(uintptr(%v))",
|
||||
}
|
||||
|
||||
// fieldTags contains parsed version of json struct field tags.
|
||||
@@ -186,8 +188,9 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT
|
||||
|
||||
case reflect.Map:
|
||||
key := t.Key()
|
||||
if key.Kind() != reflect.String {
|
||||
return fmt.Errorf("map type %v not supported: only string keys are allowed", key)
|
||||
keyEnc, ok := primitiveStringEncoders[key.Kind()]
|
||||
if !ok {
|
||||
return fmt.Errorf("map key type %v not supported: only string and integer keys are allowed", key)
|
||||
}
|
||||
tmpVar := g.uniqueVarName()
|
||||
|
||||
@@ -199,7 +202,7 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT
|
||||
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(string("+tmpVar+"Name))")
|
||||
fmt.Fprintln(g.out, ws+" "+fmt.Sprintf(keyEnc, tmpVar+"Name"))
|
||||
fmt.Fprintln(g.out, ws+" out.RawByte(':')")
|
||||
|
||||
if err := g.genTypeEncoder(t.Elem(), tmpVar+"Value", tags, indent+2); err != nil {
|
||||
|
||||
@@ -904,6 +904,10 @@ func (r *Lexer) UintStr() uint {
|
||||
return uint(r.Uint64Str())
|
||||
}
|
||||
|
||||
func (r *Lexer) UintptrStr() uintptr {
|
||||
return uintptr(r.Uint64Str())
|
||||
}
|
||||
|
||||
func (r *Lexer) Int8Str() int8 {
|
||||
s, b := r.unsafeString()
|
||||
if !r.Ok() {
|
||||
|
||||
@@ -196,6 +196,13 @@ func (w *Writer) Uint64Str(n uint64) {
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) UintptrStr(n uintptr) {
|
||||
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) Int8Str(n int8) {
|
||||
w.Buffer.EnsureSpace(4)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
|
||||
@@ -38,6 +38,15 @@ var testCases = []struct {
|
||||
{&IntsValue, IntsString},
|
||||
{&mapStringStringValue, mapStringStringString},
|
||||
{&namedTypeValue, namedTypeValueString},
|
||||
{&mapMyIntStringValue, mapMyIntStringValueString},
|
||||
{&mapIntStringValue, mapIntStringValueString},
|
||||
{&mapInt32StringValue, mapInt32StringValueString},
|
||||
{&mapInt64StringValue, mapInt64StringValueString},
|
||||
{&mapUintStringValue, mapUintStringValueString},
|
||||
{&mapUint32StringValue, mapUint32StringValueString},
|
||||
{&mapUint64StringValue, mapUint64StringValueString},
|
||||
{&mapUintptrStringValue, mapUintptrStringValueString},
|
||||
{&intKeyedMapStructValue, intKeyedMapStructValueString},
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
|
||||
@@ -692,3 +692,68 @@ type EmbeddedStruct struct {
|
||||
|
||||
var structWithInterfaceString = `{"f1":1,"f2":{"f1":11,"f2":"22"},"f3":"3"}`
|
||||
var structWithInterfaceValueFilled = StructWithInterface{1, &EmbeddedStruct{11, "22"}, "3"}
|
||||
|
||||
//easyjson:json
|
||||
type MapIntString map[int]string
|
||||
|
||||
var mapIntStringValue = MapIntString{3: "hi"}
|
||||
var mapIntStringValueString = `{"3":"hi"}`
|
||||
|
||||
//easyjson:json
|
||||
type MapInt32String map[int32]string
|
||||
|
||||
var mapInt32StringValue = MapInt32String{-354634382: "life"}
|
||||
var mapInt32StringValueString = `{"-354634382":"life"}`
|
||||
|
||||
//easyjson:json
|
||||
type MapInt64String map[int64]string
|
||||
|
||||
var mapInt64StringValue = MapInt64String{-3546343826724305832: "life"}
|
||||
var mapInt64StringValueString = `{"-3546343826724305832":"life"}`
|
||||
|
||||
//easyjson:json
|
||||
type MapUintString map[uint]string
|
||||
|
||||
var mapUintStringValue = MapUintString{42: "life"}
|
||||
var mapUintStringValueString = `{"42":"life"}`
|
||||
|
||||
//easyjson:json
|
||||
type MapUint32String map[uint32]string
|
||||
|
||||
var mapUint32StringValue = MapUint32String{354634382: "life"}
|
||||
var mapUint32StringValueString = `{"354634382":"life"}`
|
||||
|
||||
//easyjson:json
|
||||
type MapUint64String map[uint64]string
|
||||
|
||||
var mapUint64StringValue = MapUint64String{3546343826724305832: "life"}
|
||||
var mapUint64StringValueString = `{"3546343826724305832":"life"}`
|
||||
|
||||
//easyjson:json
|
||||
type MapUintptrString map[uintptr]string
|
||||
|
||||
var mapUintptrStringValue = MapUintptrString{272679208: "obj"}
|
||||
var mapUintptrStringValueString = `{"272679208":"obj"}`
|
||||
|
||||
type MyInt int
|
||||
|
||||
//easyjson:json
|
||||
type MapMyIntString map[MyInt]string
|
||||
|
||||
var mapMyIntStringValue = MapMyIntString{MyInt(42): "life"}
|
||||
var mapMyIntStringValueString = `{"42":"life"}`
|
||||
|
||||
//easyjson:json
|
||||
type IntKeyedMapStruct struct {
|
||||
Foo MapMyIntString `json:"foo"`
|
||||
Bar map[int16]MapUint32String `json:"bar"`
|
||||
}
|
||||
|
||||
var intKeyedMapStructValue = IntKeyedMapStruct{
|
||||
Foo: mapMyIntStringValue,
|
||||
Bar: map[int16]MapUint32String{32: mapUint32StringValue},
|
||||
}
|
||||
var intKeyedMapStructValueString = `{` +
|
||||
`"foo":{"42":"life"},` +
|
||||
`"bar":{"32":{"354634382":"life"}}` +
|
||||
`}`
|
||||
|
||||
@@ -21,3 +21,6 @@ type ErrorNestedStruct struct {
|
||||
ErrorStruct ErrorStruct `json:"error_struct"`
|
||||
Int int `json:"int"`
|
||||
}
|
||||
|
||||
//easyjson:json
|
||||
type ErrorIntMap map[uint32]string
|
||||
|
||||
@@ -241,3 +241,45 @@ func TestMultipleErrorsNestedStruct(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleErrorsIntMap(t *testing.T) {
|
||||
for i, test := range []struct {
|
||||
Data []byte
|
||||
Offsets []int
|
||||
}{
|
||||
{
|
||||
Data: []byte(`{"a":"NumErr"}`),
|
||||
Offsets: []int{1},
|
||||
},
|
||||
{
|
||||
Data: []byte(`{"":"ErrSyntax"}`),
|
||||
Offsets: []int{1},
|
||||
},
|
||||
{
|
||||
Data: []byte(`{"a":"NumErr","33147483647":"ErrRange","-1":"ErrRange"}`),
|
||||
Offsets: []int{1, 14, 39},
|
||||
},
|
||||
} {
|
||||
l := jlexer.Lexer{
|
||||
Data: test.Data,
|
||||
UseMultipleErrors: true,
|
||||
}
|
||||
|
||||
var v ErrorIntMap
|
||||
|
||||
v.UnmarshalEasyJSON(&l)
|
||||
|
||||
errors := l.GetNonFatalErrors()
|
||||
|
||||
if len(errors) != len(test.Offsets) {
|
||||
t.Errorf("[%d] TestMultipleErrorsInt(): errornum: want: %d, got %d", i, len(test.Offsets), len(errors))
|
||||
return
|
||||
}
|
||||
|
||||
for ii, e := range errors {
|
||||
if e.Offset != test.Offsets[ii] {
|
||||
t.Errorf("[%d] TestMultipleErrorsInt(): offset[%d]: want %d, got %d", i, ii, test.Offsets[ii], e.Offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/mailru/easyjson/gen"
|
||||
)
|
||||
|
||||
type IntMap map[int]string
|
||||
type IntMapSlice []IntMap
|
||||
type IntMapArray [2]IntMap
|
||||
type IntMapPtr *IntMap
|
||||
type IntMapMap map[string]IntMap
|
||||
|
||||
func TestNonStringKeyedtMapEncoder(t *testing.T) {
|
||||
f := "non_string_keyed_map_easyjson.go"
|
||||
for _, test := range []struct {
|
||||
Data interface{}
|
||||
}{
|
||||
{
|
||||
Data: IntMap{},
|
||||
},
|
||||
{
|
||||
Data: IntMapSlice{},
|
||||
},
|
||||
{
|
||||
Data: IntMapArray{},
|
||||
},
|
||||
{
|
||||
Data: IntMapPtr(nil),
|
||||
},
|
||||
{
|
||||
Data: IntMapMap{},
|
||||
},
|
||||
} {
|
||||
g := gen.NewGenerator(f)
|
||||
g.Add(test.Data)
|
||||
e := g.Run(os.Stdout)
|
||||
if e == nil {
|
||||
t.Errorf("generation for %#v should have errored", test.Data)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user