runtime: Deserializing duplicate JSON object keys to a dictionary
Deserializing duplicate JSON object keys to a dictionary should be thought about. They’re not common, but they’re also not disallowed by the JSON spec.
In Newtonsoft.Json key/value pairs are set into the dictionary so that the last value in an object wins. This means dictionaries align with classes when it comes to duplicate object keys: the final result is the last value.
{
"Hello": "friends",
"Hello": "world"
}
var d = JsonSerializer.Parse<Dictionary<string, string>(json);
var target = d["Hello"]; // world
Throwing an error that there is a duplicate key would prevent someone from using the serializer. S.T.J should either follow “last value wins”, or have a setting to opt into it or out of it. Newtonsoft.Json has a setting like this: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_DuplicatePropertyNameHandling.htm
This should also be considered with JsonDocument.
My recommendation is to follow “last value wins” by default in the serializer and JsonDocument, and either add a setting now or in the future to allow people to be more strict (throw an error) about duplicate JSON object keys.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 1
- Comments: 16 (15 by maintainers)
Yes it does not throw, it follows last win approach
For collections it just replaces the collections and for dictionaries it concatenates the keys. the behavior is same for System.Text.Json
I ran the performance numbers. The change improves the performance by 5-8 percent for dictionaries and for object the change doesn’t affect the performance. (Even with the linq)
The size of the object and dictionary was 30 elements. Currently the json tests are broken in performance so I just wrote new ones to test the change.
Yes - the code should be changed to use last-value-wins via TryAdd or an indexer (which doesn’t throw, unlike Add).
We could always add an opt-in option in the future to prevent duplicates.