mirror of
https://github.com/json-iterator/go.git
synced 2025-05-16 21:45:43 +02:00
Merge pull request #285 from nikhita/fix-case-sensitivity
Fix case sensitivity
This commit is contained in:
commit
f2b4162afb
@ -2,9 +2,10 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/json-iterator/go"
|
"github.com/json-iterator/go"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_use_number_for_unmarshal(t *testing.T) {
|
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.Nil(err)
|
||||||
should.Equal(`123456789123456789123456789`, output)
|
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 {
|
for k, binding := range bindings {
|
||||||
fields[k] = binding.Decoder.(*structFieldDecoder)
|
fields[k] = binding.Decoder.(*structFieldDecoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ctx.caseSensitive() {
|
||||||
for k, binding := range bindings {
|
for k, binding := range bindings {
|
||||||
if _, found := fields[strings.ToLower(k)]; !found {
|
if _, found := fields[strings.ToLower(k)]; !found {
|
||||||
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
|
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return createStructDecoder(ctx, typ, fields)
|
return createStructDecoder(ctx, typ, fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +51,7 @@ func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structF
|
|||||||
knownHash := map[int64]struct{}{
|
knownHash := map[int64]struct{}{
|
||||||
0: {},
|
0: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
switch len(fields) {
|
switch len(fields) {
|
||||||
case 0:
|
case 0:
|
||||||
return &skipObjectDecoder{typ}
|
return &skipObjectDecoder{typ}
|
||||||
@ -514,13 +519,13 @@ func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *It
|
|||||||
fieldBytes := iter.ReadStringAsSlice()
|
fieldBytes := iter.ReadStringAsSlice()
|
||||||
field = *(*string)(unsafe.Pointer(&fieldBytes))
|
field = *(*string)(unsafe.Pointer(&fieldBytes))
|
||||||
fieldDecoder = decoder.fields[field]
|
fieldDecoder = decoder.fields[field]
|
||||||
if fieldDecoder == nil {
|
if fieldDecoder == nil && !iter.cfg.caseSensitive {
|
||||||
fieldDecoder = decoder.fields[strings.ToLower(field)]
|
fieldDecoder = decoder.fields[strings.ToLower(field)]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
field = iter.ReadString()
|
field = iter.ReadString()
|
||||||
fieldDecoder = decoder.fields[field]
|
fieldDecoder = decoder.fields[field]
|
||||||
if fieldDecoder == nil {
|
if fieldDecoder == nil && !iter.cfg.caseSensitive {
|
||||||
fieldDecoder = decoder.fields[strings.ToLower(field)]
|
fieldDecoder = decoder.fields[strings.ToLower(field)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user