소스 검색

support string conversion

Tao Wen 9 년 전
부모
커밋
d80d954345
2개의 변경된 파일65개의 추가작업 그리고 11개의 파일을 삭제
  1. 30 1
      jsoniter_reflect.go
  2. 35 10
      jsoniter_reflect_test.go

+ 30 - 1
jsoniter_reflect.go

@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"unsafe"
 	"sync/atomic"
+	"strings"
 )
 
 type Decoder interface {
@@ -110,6 +111,24 @@ func (decoder *boolDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
 	*((*bool)(ptr)) = iter.ReadBool()
 }
 
+type stringNumberDecoder struct {
+	elemDecoder Decoder
+}
+
+func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+	c := iter.readByte()
+	if c != '"' {
+		iter.ReportError("stringNumberDecoder", `expect "`)
+		return
+	}
+	decoder.elemDecoder.decode(ptr, iter)
+	c = iter.readByte()
+	if c != '"' {
+		iter.ReportError("stringNumberDecoder", `expect "`)
+		return
+	}
+}
+
 type optionalDecoder struct {
 	valueType reflect.Type
 	valueDecoder Decoder
@@ -327,11 +346,21 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) {
 	fields := map[string]Decoder{}
 	for i := 0; i < type_.NumField(); i++ {
 		field := type_.Field(i)
+		tagParts := strings.Split(field.Tag.Get("json"), ",")
+		jsonFieldName := tagParts[0]
+		if jsonFieldName == "" {
+			jsonFieldName = field.Name
+		}
 		decoder, err := decoderOfPtr(field.Type)
 		if err != nil {
 			return prefix(fmt.Sprintf("{%s}", field.Name)).addTo(decoder, err)
 		}
-		fields[field.Name] = &structFieldDecoder{field.Offset, decoder}
+		if len(tagParts) > 1 && tagParts[1] == "string" {
+			decoder = &stringNumberDecoder{decoder}
+		}
+		if jsonFieldName != "-" {
+			fields[jsonFieldName] = &structFieldDecoder{field.Offset, decoder}
+		}
 	}
 	return &structDecoder{fields}, nil
 }

+ 35 - 10
jsoniter_reflect_test.go

@@ -187,9 +187,34 @@ func Test_reflect_struct_string_ptr(t *testing.T) {
 		t.Fatal(struct_.field1)
 	}
 	if *struct_.field2 != "world" {
+		fmt.Println(iter.Error)
+		t.Fatal(struct_.field2)
+	}
+}
+
+
+type StructOfTag struct {
+	field1 string `json:"field-1"`
+	field2 string `json:"-"`
+	field3 int `json:",string"`
+}
+
+func Test_reflect_struct_tag_field(t *testing.T) {
+	iter := ParseString(`{"field-1": "hello", "field2": "", "field3": "100"}`)
+	struct_ := StructOfTag{field2: "world"}
+	iter.Read(&struct_)
+	if struct_.field1 != "hello" {
 		fmt.Println(iter.Error)
 		t.Fatal(struct_.field1)
 	}
+	if struct_.field2 != "world" {
+		fmt.Println(iter.Error)
+		t.Fatal(struct_.field2)
+	}
+	if struct_.field3 != 100 {
+		fmt.Println(iter.Error)
+		t.Fatal(struct_.field3)
+	}
 }
 
 func Test_reflect_slice(t *testing.T) {
@@ -235,12 +260,12 @@ func Test_reflect_nested(t *testing.T) {
 func Benchmark_jsoniter_reflect(b *testing.B) {
 	b.ReportAllocs()
 	for n := 0; n < b.N; n++ {
-		//iter := ParseString(`{"field1": "hello", "field2": "world"}`)
-		//struct_ := StructOfString{}
-		//iter.Read(&struct_)
-		iter := ParseString(`["hello", "world"]`)
-		array := make([]string, 0, 1)
-		iter.Read(&array)
+		iter := ParseString(`{"field3": "100"}`)
+		struct_ := StructOfTag{}
+		iter.Read(&struct_)
+		//iter := ParseString(`["hello", "world"]`)
+		//array := make([]string, 0, 1)
+		//iter.Read(&array)
 	}
 }
 
@@ -270,9 +295,9 @@ func Benchmark_jsoniter_direct(b *testing.B) {
 func Benchmark_json_reflect(b *testing.B) {
 	b.ReportAllocs()
 	for n := 0; n < b.N; n++ {
-		//struct_ := StructOfString{}
-		//json.Unmarshal([]byte(`{"field1": "hello", "field2": "world"}`), &struct_)
-		array := make([]string, 0, 2)
-		json.Unmarshal([]byte(`["hello", "world"]`), &array)
+		struct_ := StructOfTag{}
+		json.Unmarshal([]byte(`{"field3": "100"}`), &struct_)
+		//array := make([]string, 0, 2)
+		//json.Unmarshal([]byte(`["hello", "world"]`), &array)
 	}
 }