Skip to content

Fix case sensitivity #285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 12, 2018
Merged

Conversation

nikhita
Copy link
Contributor

@nikhita nikhita commented Jun 11, 2018

@nikhita
Copy link
Contributor Author

nikhita commented Jun 11, 2018

@codecov
Copy link

codecov bot commented Jun 11, 2018

Codecov Report

Merging #285 into master will increase coverage by 0.08%.
The diff coverage is 83.33%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #285      +/-   ##
==========================================
+ Coverage   81.38%   81.46%   +0.08%     
==========================================
  Files          41       41              
  Lines        4979     4980       +1     
==========================================
+ Hits         4052     4057       +5     
  Misses        807      807              
+ Partials      120      116       -4
Impacted Files Coverage Δ
reflect_struct_decoder.go 45.68% <83.33%> (-0.63%) ⬇️
reflect_native.go 88.12% <0%> (+0.76%) ⬆️
iter_int.go 90.37% <0%> (+1.67%) ⬆️
iter_object.go 66.66% <0%> (+1.69%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7cceb6c...3830516. Read the comment docs.

if !ctx.caseSensitive() {
for k, binding := range bindings {
if _, found := fields[strings.ToLower(k)]; !found {
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
Copy link
Contributor

@liggitt liggitt Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the toLower calls on lines 521 and 527 need conditionalizing as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if so, is there a test case that could exercise that path?

Copy link
Contributor Author

@nikhita nikhita Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the toLower calls on lines 521 and 527 need conditionalizing as well?

I don't think so. In fact, I don't think we even need to check for the nil condition there.

fieldDecoder = decoder.fields[field]
if fieldDecoder == nil {
fieldDecoder = decoder.fields[strings.ToLower(field)]
}

Here decoder is a generalStructDecoder, which is created here:

return &generalStructDecoder{typ, fields, false}

The fields in this struct comes from:

fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder)
}

The *structFieldDecoder is a *StructDescriptor which is created from:

structDescriptor := describeStruct(ctx, typ)

func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {

which creates from:

go/reflect_extension.go

Lines 388 to 391 in 7cceb6c

func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
structDescriptor := &StructDescriptor{
Type: typ,
Fields: bindings,

From the above snippet ^, *StructDescriptor can never be nil.

Also, if the decoder is supposed to be case sensitive, the conversion to lower case is taken care of while constructing the struct decoder:

for k, binding := range bindings {
if _, found := fields[strings.ToLower(k)]; !found {
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
}
}

so the toLower() which is used below in lines 521 and 527 is not called and not needed.

Copy link
Contributor Author

@nikhita nikhita Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this makes sense, I'll remove the lines. But I want to first double check if this is indeed correct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if the decoder is supposed to be case sensitive, the conversion to lower case is take care of while constructing the struct decoder:

That's my understanding as well. I agree that we should remove the lines.

Copy link
Contributor Author

@nikhita nikhita Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's my understanding as well. I agree that we should remove the lines.

Removed. (tests were failing, investigating why)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, if the decoder is case insensitive, we need to keep the lines, because decoder.fields[field] might return empty, and we can only find the decoder via decoder.fields[strings.ToLower(field)].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, added back the lines along with a new test case.

And if so, is there a test case that could exercise that path?

@liggitt the case insensitive ones are the ones that exercise the path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, added back the lines along with a new test case.

+1

@nikhita nikhita force-pushed the fix-case-sensitivity branch 3 times, most recently from 0fd1038 to 9837bb9 Compare June 11, 2018 20:26
@caesarxuchao
Copy link
Contributor

@nikhita I found the root cause of not ignoring spec.reliCAs. It's because the DeploymentSpec struct has 11 fields (field whose json name has camelCase counts as 2), so it gets the generalStructDecoder at https://github.com/json-iterator/go/blob/master/reflect_struct_decoder.go#L485. Before your PR, the generalStructDecoder always does decoder.fields[strings.ToLower(field)], and thus decodes spec.repliCAs.

I think in the test cases, we need to add a case where a struct has more than 11 fields, to exercise the generalStructDecoder path.

Btw, we might have accidentally improved the performance of jsoniter. Before our fixes, as long as a struct has camelCase field names, the decoder will always be the generalStructDecoder because it always hits

fieldHash := calcHash(fieldName, ctx.caseSensitive())
_, known := knownHash[fieldHash]
if known {
return &generalStructDecoder{typ, fields, false}
}

@nikhita nikhita force-pushed the fix-case-sensitivity branch from 9837bb9 to 3830516 Compare June 12, 2018 05:54
@nikhita
Copy link
Contributor Author

nikhita commented Jun 12, 2018

@caesarxuchao updated.

Btw, we might have accidentally improved the performance of jsoniter.

🎉

@caesarxuchao
Copy link
Contributor

lgtm

@thockin
Copy link
Collaborator

thockin commented Jun 12, 2018

We should add an equivalent case-sensitivity test to k8s, so that any future changes in JSON parsing catch it.

@thockin
Copy link
Collaborator

thockin commented Jun 12, 2018

LGTM

By the power vested in me, I hereby merge your fix.

@thockin thockin merged commit f2b4162 into json-iterator:master Jun 12, 2018
@nikhita nikhita deleted the fix-case-sensitivity branch June 3, 2019 17:01
zhenzou pushed a commit to zhenzou/jsoniter that referenced this pull request Feb 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants