mirror of
https://github.com/json-iterator/go.git
synced 2025-01-08 13:06:29 +02:00
optimize struct reflect
This commit is contained in:
parent
42a4f2c11d
commit
87a35bd7e4
@ -149,7 +149,7 @@ func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
}
|
||||
|
||||
type structDecoder struct {
|
||||
type_ reflect.Type
|
||||
type_ reflect.Type
|
||||
fields map[string]Decoder
|
||||
}
|
||||
|
||||
@ -167,8 +167,122 @@ func (decoder *structDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
}
|
||||
}
|
||||
|
||||
type skipDecoder struct {
|
||||
type_ reflect.Type
|
||||
}
|
||||
|
||||
func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
iter.Skip()
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type oneFieldStructDecoder struct {
|
||||
type_ reflect.Type
|
||||
fieldName string
|
||||
fieldDecoder Decoder
|
||||
}
|
||||
|
||||
func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
||||
if field == decoder.fieldName {
|
||||
decoder.fieldDecoder.decode(ptr, iter)
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type twoFieldsStructDecoder struct {
|
||||
type_ reflect.Type
|
||||
fieldName1 string
|
||||
fieldDecoder1 Decoder
|
||||
fieldName2 string
|
||||
fieldDecoder2 Decoder
|
||||
}
|
||||
|
||||
func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
||||
switch field {
|
||||
case decoder.fieldName1:
|
||||
decoder.fieldDecoder1.decode(ptr, iter)
|
||||
case decoder.fieldName2:
|
||||
decoder.fieldDecoder2.decode(ptr, iter)
|
||||
default:
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type threeFieldsStructDecoder struct {
|
||||
type_ reflect.Type
|
||||
fieldName1 string
|
||||
fieldDecoder1 Decoder
|
||||
fieldName2 string
|
||||
fieldDecoder2 Decoder
|
||||
fieldName3 string
|
||||
fieldDecoder3 Decoder
|
||||
}
|
||||
|
||||
func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
||||
switch field {
|
||||
case decoder.fieldName1:
|
||||
decoder.fieldDecoder1.decode(ptr, iter)
|
||||
case decoder.fieldName2:
|
||||
decoder.fieldDecoder2.decode(ptr, iter)
|
||||
case decoder.fieldName3:
|
||||
decoder.fieldDecoder3.decode(ptr, iter)
|
||||
default:
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type fourFieldsStructDecoder struct {
|
||||
type_ reflect.Type
|
||||
fieldName1 string
|
||||
fieldDecoder1 Decoder
|
||||
fieldName2 string
|
||||
fieldDecoder2 Decoder
|
||||
fieldName3 string
|
||||
fieldDecoder3 Decoder
|
||||
fieldName4 string
|
||||
fieldDecoder4 Decoder
|
||||
}
|
||||
|
||||
func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
||||
switch field {
|
||||
case decoder.fieldName1:
|
||||
decoder.fieldDecoder1.decode(ptr, iter)
|
||||
case decoder.fieldName2:
|
||||
decoder.fieldDecoder2.decode(ptr, iter)
|
||||
case decoder.fieldName3:
|
||||
decoder.fieldDecoder3.decode(ptr, iter)
|
||||
case decoder.fieldName4:
|
||||
decoder.fieldDecoder4.decode(ptr, iter)
|
||||
default:
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type structFieldDecoder struct {
|
||||
field *reflect.StructField
|
||||
field *reflect.StructField
|
||||
fieldDecoder Decoder
|
||||
}
|
||||
|
||||
@ -412,6 +526,77 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
|
||||
fields[jsonFieldName] = &structFieldDecoder{&field, decoder}
|
||||
}
|
||||
}
|
||||
switch len(fields) {
|
||||
case 0:
|
||||
return &skipDecoder{type_}, nil
|
||||
case 1:
|
||||
for fieldName, fieldDecoder := range fields {
|
||||
return &oneFieldStructDecoder{type_, fieldName, fieldDecoder}, nil
|
||||
}
|
||||
case 2:
|
||||
var fieldName1 string
|
||||
var fieldName2 string
|
||||
var fieldDecoder1 Decoder
|
||||
var fieldDecoder2 Decoder
|
||||
for fieldName, fieldDecoder := range fields {
|
||||
if fieldName1 == "" {
|
||||
fieldName1 = fieldName
|
||||
fieldDecoder1 = fieldDecoder
|
||||
} else {
|
||||
fieldName2 = fieldName
|
||||
fieldDecoder2 = fieldDecoder
|
||||
}
|
||||
}
|
||||
return &twoFieldsStructDecoder{type_, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil
|
||||
case 3:
|
||||
var fieldName1 string
|
||||
var fieldName2 string
|
||||
var fieldName3 string
|
||||
var fieldDecoder1 Decoder
|
||||
var fieldDecoder2 Decoder
|
||||
var fieldDecoder3 Decoder
|
||||
for fieldName, fieldDecoder := range fields {
|
||||
if fieldName1 == "" {
|
||||
fieldName1 = fieldName
|
||||
fieldDecoder1 = fieldDecoder
|
||||
} else if fieldName2 == "" {
|
||||
fieldName2 = fieldName
|
||||
fieldDecoder2 = fieldDecoder
|
||||
} else {
|
||||
fieldName3 = fieldName
|
||||
fieldDecoder3 = fieldDecoder
|
||||
}
|
||||
}
|
||||
return &threeFieldsStructDecoder{type_,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
|
||||
case 4:
|
||||
var fieldName1 string
|
||||
var fieldName2 string
|
||||
var fieldName3 string
|
||||
var fieldName4 string
|
||||
var fieldDecoder1 Decoder
|
||||
var fieldDecoder2 Decoder
|
||||
var fieldDecoder3 Decoder
|
||||
var fieldDecoder4 Decoder
|
||||
for fieldName, fieldDecoder := range fields {
|
||||
if fieldName1 == "" {
|
||||
fieldName1 = fieldName
|
||||
fieldDecoder1 = fieldDecoder
|
||||
} else if fieldName2 == "" {
|
||||
fieldName2 = fieldName
|
||||
fieldDecoder2 = fieldDecoder
|
||||
} else if fieldName3 == "" {
|
||||
fieldName3 = fieldName
|
||||
fieldDecoder3 = fieldDecoder
|
||||
} else {
|
||||
fieldName4 = fieldName
|
||||
fieldDecoder4 = fieldDecoder
|
||||
}
|
||||
}
|
||||
return &fourFieldsStructDecoder{type_,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4}, nil
|
||||
}
|
||||
return &structDecoder{type_, fields}, nil
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,6 @@ func Test_reflect_struct_string_ptr(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type StructOfTag struct {
|
||||
field1 string `json:"field-1"`
|
||||
field2 string `json:"-"`
|
||||
@ -257,11 +256,19 @@ func Test_reflect_nested(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type StructOfTagOne struct {
|
||||
field1 string `json:"field1"`
|
||||
field2 string `json:"field2"`
|
||||
field3 int `json:"field3,string"`
|
||||
field4 int `json:"field4,string"`
|
||||
}
|
||||
|
||||
func Benchmark_jsoniter_reflect(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
iter := ParseString(`{"field3": "100"}`)
|
||||
struct_ := StructOfTag{}
|
||||
struct_ := StructOfTagOne{}
|
||||
iter.Read(&struct_)
|
||||
//iter := ParseString(`["hello", "world"]`)
|
||||
//array := make([]string, 0, 1)
|
||||
@ -295,7 +302,7 @@ func Benchmark_jsoniter_direct(b *testing.B) {
|
||||
func Benchmark_json_reflect(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
struct_ := StructOfTag{}
|
||||
struct_ := StructOfTagOne{}
|
||||
json.Unmarshal([]byte(`{"field3": "100"}`), &struct_)
|
||||
//array := make([]string, 0, 2)
|
||||
//json.Unmarshal([]byte(`["hello", "world"]`), &array)
|
||||
|
Loading…
Reference in New Issue
Block a user