1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-24 08:22:14 +02:00

support customize all fields

This commit is contained in:
Tao Wen 2016-12-12 19:06:33 +08:00
parent 39a6ced9d0
commit 9fe4625ee2
2 changed files with 46 additions and 5 deletions

View File

@ -5,6 +5,7 @@ import (
"time" "time"
"unsafe" "unsafe"
"strconv" "strconv"
"reflect"
) )
func Test_customize_type_decoder(t *testing.T) { func Test_customize_type_decoder(t *testing.T) {
@ -42,4 +43,23 @@ func Test_customize_field_decoder(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
}
func Test_customize_field_decoder_factory(t *testing.T) {
RegisterFieldCustomizer(func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc) {
if (type_.String() == "jsoniter.Tom" && field.Name == "field1") {
return []string{"field-1"}, func(ptr unsafe.Pointer, iter *Iterator) {
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
}
}
return nil, nil
})
tom := Tom{}
err := Unmarshal([]byte(`{"field-1": 100}`), &tom)
if err != nil {
t.Fatal(err)
}
if tom.field1 != "100" {
t.Fatal(tom.field1)
}
} }

View File

@ -450,14 +450,17 @@ func getDecoderFromCache(cacheKey reflect.Type) Decoder {
var typeDecoders map[string]Decoder var typeDecoders map[string]Decoder
var fieldDecoders map[string]Decoder var fieldDecoders map[string]Decoder
var fieldCustomizers []FieldCustomizerFunc
func init() { func init() {
typeDecoders = map[string]Decoder{} typeDecoders = map[string]Decoder{}
fieldDecoders = map[string]Decoder{} fieldDecoders = map[string]Decoder{}
fieldCustomizers = []FieldCustomizerFunc{}
atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{})) atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{}))
} }
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
type FieldCustomizerFunc func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc)
type funcDecoder struct { type funcDecoder struct {
func_ DecoderFunc func_ DecoderFunc
@ -475,6 +478,10 @@ func RegisterFieldDecoder(type_ string, field string, func_ DecoderFunc) {
fieldDecoders[fmt.Sprintf("%s/%s", type_, field)] = &funcDecoder{func_} fieldDecoders[fmt.Sprintf("%s/%s", type_, field)] = &funcDecoder{func_}
} }
func RegisterFieldCustomizer(func_ FieldCustomizerFunc) {
fieldCustomizers = append(fieldCustomizers, func_)
}
func ClearDecoders() { func ClearDecoders() {
typeDecoders = map[string]Decoder{} typeDecoders = map[string]Decoder{}
fieldDecoders = map[string]Decoder{} fieldDecoders = map[string]Decoder{}
@ -686,11 +693,25 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
for i := 0; i < type_.NumField(); i++ { for i := 0; i < type_.NumField(); i++ {
field := type_.Field(i) field := type_.Field(i)
fieldDecoderKey := fmt.Sprintf("%s/%s", type_.String(), field.Name) fieldDecoderKey := fmt.Sprintf("%s/%s", type_.String(), field.Name)
var fieldNames []string
for _, customizer := range fieldCustomizers {
alternativeFieldNames, func_ := customizer(type_, &field)
if alternativeFieldNames != nil {
fieldNames = alternativeFieldNames
}
if func_ != nil {
fieldDecoders[fieldDecoderKey] = &funcDecoder{func_}
}
}
decoder := fieldDecoders[fieldDecoderKey] decoder := fieldDecoders[fieldDecoderKey]
tagParts := strings.Split(field.Tag.Get("json"), ",") tagParts := strings.Split(field.Tag.Get("json"), ",")
jsonFieldName := tagParts[0] if fieldNames == nil {
if jsonFieldName == "" { switch tagParts[0] {
jsonFieldName = field.Name case "":
fieldNames = []string{field.Name}
case "-":
fieldNames = []string{}
}
} }
if decoder == nil { if decoder == nil {
var err error var err error
@ -702,8 +723,8 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
if len(tagParts) > 1 && tagParts[1] == "string" { if len(tagParts) > 1 && tagParts[1] == "string" {
decoder = &stringNumberDecoder{decoder} decoder = &stringNumberDecoder{decoder}
} }
if jsonFieldName != "-" { for _, fieldName := range fieldNames {
fields[jsonFieldName] = &structFieldDecoder{&field, decoder} fields[fieldName] = &structFieldDecoder{&field, decoder}
} }
} }
switch len(fields) { switch len(fields) {