Ver código fonte

support customize all fields

Tao Wen 9 anos atrás
pai
commit
9fe4625ee2
2 arquivos alterados com 46 adições e 5 exclusões
  1. 20 0
      jsoniter_customize_test.go
  2. 26 5
      jsoniter_reflect.go

+ 20 - 0
jsoniter_customize_test.go

@@ -5,6 +5,7 @@ import (
 	"time"
 	"unsafe"
 	"strconv"
+	"reflect"
 )
 
 func Test_customize_type_decoder(t *testing.T) {
@@ -42,4 +43,23 @@ func Test_customize_field_decoder(t *testing.T) {
 	if err != nil {
 		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)
+	}
 }

+ 26 - 5
jsoniter_reflect.go

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