// Set the sorted property cache. Overwrite any existing cache which can occur in multi-threaded cases.
if (frame.PropertyRefCache != null)
{
- List<PropertyRef> cache = frame.PropertyRefCache;
+ HashSet<PropertyRef> cache = frame.PropertyRefCache;
// Add any missing properties. This creates a consistent cache count which is important for
// the loop in GetProperty() when there are multiple threads in a race conditions each generating
for (int iProperty = 0; iProperty < _propertyRefs.Count; iProperty++)
{
PropertyRef propertyRef = _propertyRefs[iProperty];
- bool found = false;
- int iCacheProperty = 0;
-
- for (; iCacheProperty < cache.Count; iCacheProperty++)
- {
- if (IsPropertyRefEqual(ref propertyRef, cache[iCacheProperty]))
- {
- // The property is already cached, skip to the next property.
- found = true;
- break;
- }
- }
-
- if (found == false)
- {
- cache.Add(propertyRef);
- break;
- }
+ // Cache the missing property or override the existing property.
+ cache.Add(propertyRef);
}
}
Debug.Assert(cache.Count == _propertyRefs.Count);
- _propertyRefsSorted = cache.ToArray();
+ if (_propertyRefsSorted == null || _propertyRefsSorted.Length < cache.Count)
+ {
+ _propertyRefsSorted = new PropertyRef[cache.Count];
+ }
+ cache.CopyTo(_propertyRefsSorted);
frame.PropertyRefCache = null;
}
}
if (propertyIndex == 0 && frame.PropertyRefCache == null)
{
// Create the temporary list on first property access to prevent a partially filled List.
- frame.PropertyRefCache = new List<PropertyRef>();
+ frame.PropertyRefCache = new HashSet<PropertyRef>();
}
if (info != null)
// For performance, we order the properties by the first deserialize and PropertyIndex helps find the right slot quicker.
public int PropertyIndex;
- public List<PropertyRef> PropertyRefCache;
+ public HashSet<PropertyRef> PropertyRefCache;
// The current JSON data for a property does not match a given POCO, so ignore the property (recursively).
public bool Drain;
Assert.Null(dictionaryObject["Hello"]);
}
+ [Fact]
+ public static void DeserializeDictionaryWithDuplicateProperties()
+ {
+ PocoDuplicate foo = JsonSerializer.Parse<PocoDuplicate>(@"{""BoolProperty"": false, ""BoolProperty"": true}");
+ Assert.True(foo.BoolProperty);
+
+ foo = JsonSerializer.Parse<PocoDuplicate>(@"{""BoolProperty"": false, ""IntProperty"" : 1, ""BoolProperty"": true , ""IntProperty"" : 2}");
+ Assert.True(foo.BoolProperty);
+ Assert.Equal(2, foo.IntProperty);
+
+ foo = JsonSerializer.Parse<PocoDuplicate>(@"{""DictProperty"" : {""a"" : ""b"", ""c"" : ""d""},""DictProperty"" : {""b"" : ""b"", ""c"" : ""e""}}");
+ Assert.Equal(3, foo.DictProperty.Count);
+ Assert.Equal("e", foo.DictProperty["c"]);
+ }
+
+ public class PocoDuplicate
+ {
+ public bool BoolProperty { get; set; }
+ public int IntProperty { get; set; }
+ public Dictionary<string, string> DictProperty { get; set; }
+ }
+
[Fact]
public static void ClassWithNoSetter()
{