You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	Merge pull request #285 from nikhita/fix-case-sensitivity
Fix case sensitivity
This commit is contained in:
		| @@ -2,9 +2,10 @@ package test | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/json-iterator/go" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_use_number_for_unmarshal(t *testing.T) { | ||||
| @@ -45,3 +46,129 @@ func Test_read_large_number_as_interface(t *testing.T) { | ||||
| 	should.Nil(err) | ||||
| 	should.Equal(`123456789123456789123456789`, output) | ||||
| } | ||||
|  | ||||
| type caseSensitiveStruct struct { | ||||
| 	A string `json:"a"` | ||||
| 	B string `json:"b,omitempty"` | ||||
| 	C *C     `json:"C,omitempty"` | ||||
| } | ||||
|  | ||||
| type C struct { | ||||
| 	D int64 `json:"D,omitempty"` | ||||
| 	E *E    `json:"e,omitempty"` | ||||
| } | ||||
|  | ||||
| type E struct { | ||||
| 	F string `json:"F,omitempty"` | ||||
| } | ||||
|  | ||||
| func Test_CaseSensitive(t *testing.T) { | ||||
| 	should := require.New(t) | ||||
|  | ||||
| 	testCases := []struct { | ||||
| 		input          string | ||||
| 		expectedOutput string | ||||
| 		caseSensitive  bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			input:          `{"A":"foo","B":"bar"}`, | ||||
| 			expectedOutput: `{"a":"foo","b":"bar"}`, | ||||
| 			caseSensitive:  false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"a":"foo","b":"bar"}`, | ||||
| 			expectedOutput: `{"a":"foo","b":"bar"}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"a":"foo","b":"bar","C":{"D":10}}`, | ||||
| 			expectedOutput: `{"a":"foo","b":"bar","C":{"D":10}}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"a":"foo","B":"bar","c":{"d":10}}`, | ||||
| 			expectedOutput: `{"a":"foo"}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"a":"foo","C":{"d":10}}`, | ||||
| 			expectedOutput: `{"a":"foo","C":{}}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"a":"foo","C":{"D":10,"e":{"f":"baz"}}}`, | ||||
| 			expectedOutput: `{"a":"foo","C":{"D":10,"e":{}}}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`, | ||||
| 			expectedOutput: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"A":"foo","c":{"d":10,"E":{"f":"baz"}}}`, | ||||
| 			expectedOutput: `{"a":"foo","C":{"D":10,"e":{"F":"baz"}}}`, | ||||
| 			caseSensitive:  false, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range testCases { | ||||
| 		val := caseSensitiveStruct{} | ||||
| 		err := jsoniter.Config{CaseSensitive: tc.caseSensitive}.Froze().UnmarshalFromString(tc.input, &val) | ||||
| 		should.Nil(err) | ||||
|  | ||||
| 		output, err := jsoniter.MarshalToString(val) | ||||
| 		should.Nil(err) | ||||
| 		should.Equal(tc.expectedOutput, output) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type structWithElevenFields struct { | ||||
| 	A string `json:"A,omitempty"` | ||||
| 	B string `json:"B,omitempty"` | ||||
| 	C string `json:"C,omitempty"` | ||||
| 	D string `json:"d,omitempty"` | ||||
| 	E string `json:"e,omitempty"` | ||||
| 	F string `json:"f,omitempty"` | ||||
| 	G string `json:"g,omitempty"` | ||||
| 	H string `json:"h,omitempty"` | ||||
| 	I string `json:"i,omitempty"` | ||||
| 	J string `json:"j,omitempty"` | ||||
| 	K string `json:"k,omitempty"` | ||||
| } | ||||
|  | ||||
| func Test_CaseSensitive_MoreThanTenFields(t *testing.T) { | ||||
| 	should := require.New(t) | ||||
|  | ||||
| 	testCases := []struct { | ||||
| 		input          string | ||||
| 		expectedOutput string | ||||
| 		caseSensitive  bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			input:          `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"10","k":"11"}`, | ||||
| 			expectedOutput: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"10","k":"11"}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"a":"1","b":"2","c":"3","D":"4","E":"5","F":"6"}`, | ||||
| 			expectedOutput: `{"A":"1","B":"2","C":"3","d":"4","e":"5","f":"6"}`, | ||||
| 			caseSensitive:  false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:          `{"A":"1","b":"2","d":"4","E":"5"}`, | ||||
| 			expectedOutput: `{"A":"1","d":"4"}`, | ||||
| 			caseSensitive:  true, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range testCases { | ||||
| 		val := structWithElevenFields{} | ||||
| 		err := jsoniter.Config{CaseSensitive: tc.caseSensitive}.Froze().UnmarshalFromString(tc.input, &val) | ||||
| 		should.Nil(err) | ||||
|  | ||||
| 		output, err := jsoniter.MarshalToString(val) | ||||
| 		should.Nil(err) | ||||
| 		should.Equal(tc.expectedOutput, output) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -32,11 +32,15 @@ func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { | ||||
| 	for k, binding := range bindings { | ||||
| 		fields[k] = binding.Decoder.(*structFieldDecoder) | ||||
| 	} | ||||
| 	for k, binding := range bindings { | ||||
| 		if _, found := fields[strings.ToLower(k)]; !found { | ||||
| 			fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) | ||||
|  | ||||
| 	if !ctx.caseSensitive() { | ||||
| 		for k, binding := range bindings { | ||||
| 			if _, found := fields[strings.ToLower(k)]; !found { | ||||
| 				fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return createStructDecoder(ctx, typ, fields) | ||||
| } | ||||
|  | ||||
| @@ -47,6 +51,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF | ||||
| 	knownHash := map[int64]struct{}{ | ||||
| 		0: {}, | ||||
| 	} | ||||
|  | ||||
| 	switch len(fields) { | ||||
| 	case 0: | ||||
| 		return &skipObjectDecoder{typ} | ||||
| @@ -514,13 +519,13 @@ func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *It | ||||
| 		fieldBytes := iter.ReadStringAsSlice() | ||||
| 		field = *(*string)(unsafe.Pointer(&fieldBytes)) | ||||
| 		fieldDecoder = decoder.fields[field] | ||||
| 		if fieldDecoder == nil { | ||||
| 		if fieldDecoder == nil && !iter.cfg.caseSensitive { | ||||
| 			fieldDecoder = decoder.fields[strings.ToLower(field)] | ||||
| 		} | ||||
| 	} else { | ||||
| 		field = iter.ReadString() | ||||
| 		fieldDecoder = decoder.fields[field] | ||||
| 		if fieldDecoder == nil { | ||||
| 		if fieldDecoder == nil && !iter.cfg.caseSensitive { | ||||
| 			fieldDecoder = decoder.fields[strings.ToLower(field)] | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user