Fix duplicate key detection when first value is null#3006
Fix duplicate key detection when first value is null#3006eamonnmcmanus merged 2 commits intogoogle:mainfrom
Conversation
MapTypeAdapterFactory detected duplicate map keys by checking the
return value of Map.put(): `if (replaced != null)`. This missed
duplicates where the first value was null, because Map.put() returns
null (the previous value) which passed the != null check.
For example, {"a":null,"a":1} was silently accepted as {a=1} instead
of throwing JsonSyntaxException("duplicate key: a").
Fix: check Map.containsKey() before put() instead of relying on the
return value of put(). This correctly detects duplicates regardless
of whether the first value is null.
Fixes both the object form and the array-of-entries form
(enableComplexMapKeySerialization).
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Thanks! There's a small compatibility risk, in that some client code may have been implicitly relying on the old behaviour. I'm going to run this change past all of Google's internal tests and if there are no problems I think we can assume that the change is OK. |
eamonnmcmanus
left a comment
There was a problem hiding this comment.
No issues found when running all of Google's internal tests against this change.
Summary
MapTypeAdapterFactorydetected duplicate map keys during deserialization by checking the return value ofMap.put():This fails when the first occurrence of a duplicate key maps to
null.Map.put()returns the previous value, which isnull, so the check silently passes. The duplicate is accepted without throwing.Example:
gson.fromJson("{\"a\":null,\"a\":1}", type)returns{a=1}instead of throwingJsonSyntaxException("duplicate key: a").Fix
Check
Map.containsKey(key)before callingput()instead of relying on the return value ofput():Applied to both the object-form path and the array-of-entries path (
enableComplexMapKeySerialization).Tests added
MapTest.testMapDeserializationWithDuplicateKeysNullFirstValue— null first value, non-null secondMapTest.testMapDeserializationWithDuplicateKeysBothNull— both values nullMapAsArrayTypeAdapterTest.testDuplicateKeyWithNullFirstValueArrayForm— array-of-entries formAll 4,589 existing tests continue to pass.
How this was found
This bug was found by an AI-assisted code review generated by quality-playbook, an open-source skill for AI-driven code review. The playbook derived null-handling requirements from Gson's community documentation (GitHub issues #676, #913, #948, #1558), then used those requirements to ground a three-pass code review. The review flagged the
replaced != nullcheck as insufficient for null values — a finding that was then manually verified with a failing test.