// Convert non-immutable dictionary interfaces to concrete types.
if (propertyType.IsInterface && jsonInfo.ClassType == ClassType.Dictionary)
{
- // If a polymorphic case, we have to wait until run-time values are processed.
- if (jsonInfo.ElementClassInfo.ClassType != ClassType.Unknown || propertyType == typeof(IDictionary))
+ JsonClassInfo elementClassInfo = jsonInfo.ElementClassInfo;
+ JsonPropertyInfo elementPropertyInfo = options.GetJsonPropertyInfoFromClassInfo(elementClassInfo, options);
+
+ Type newPropertyType = elementPropertyInfo.GetDictionaryConcreteType();
+ if (propertyType != newPropertyType)
{
- Type newPropertyType = jsonInfo.ElementClassInfo.GetPolicyProperty().GetDictionaryConcreteType();
- if (propertyType != newPropertyType)
- {
- jsonInfo = CreateProperty(propertyType, newPropertyType, propertyInfo, classType, options);
- }
+ jsonInfo = CreateProperty(propertyType, newPropertyType, propertyInfo, classType, options);
}
}
else if (jsonInfo.ClassType == ClassType.Enumerable &&
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
return true;
}
- state.Current.Enumerator = ((IDictionary)enumerable).GetEnumerator();
+ if (enumerable is IDictionary dictionary)
+ {
+ state.Current.Enumerator = dictionary.GetEnumerator();
+ }
+ else
+ {
+ state.Current.Enumerator = enumerable.GetEnumerator();
+ }
+
state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer);
}
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
+using Newtonsoft.Json;
using Xunit;
namespace System.Text.Json.Serialization.Tests
public static void DictionaryOfObject()
{
{
- IDictionary obj = JsonSerializer.Parse<IDictionary>(@"{""Key1"":1}");
+ Dictionary<string, object> obj = JsonSerializer.Parse<Dictionary<string, object>>(@"{""Key1"":1}");
Assert.Equal(1, obj.Count);
JsonElement element = (JsonElement)obj["Key1"];
Assert.Equal(JsonValueType.Number, element.Type);
}
{
- Dictionary<string, object> obj = JsonSerializer.Parse<Dictionary<string, object>>(@"{""Key1"":1}");
+ IDictionary<string, object> obj = JsonSerializer.Parse<IDictionary<string, object>>(@"{""Key1"":1}");
Assert.Equal(1, obj.Count);
JsonElement element = (JsonElement)obj["Key1"];
Assert.Equal(JsonValueType.Number, element.Type);
}
}
+ [Fact]
+ public static void ImplementsIDictionaryOfObject()
+ {
+ var input = new StringToObjectIDictionaryWrapper(new Dictionary<string, object>
+ {
+ { "Name", "David" },
+ { "Age", 32 }
+ });
+
+ string json = JsonSerializer.ToString(input, typeof(IDictionary<string, object>));
+ Assert.Equal(@"{""Name"":""David"",""Age"":32}", json);
+
+ IDictionary<string, object> obj = JsonSerializer.Parse<IDictionary<string, object>>(json);
+ Assert.Equal(2, obj.Count);
+ Assert.Equal("David", ((JsonElement)obj["Name"]).GetString());
+ Assert.Equal(32, ((JsonElement)obj["Age"]).GetInt32());
+ }
+
+ [Fact]
+ public static void ImplementsIDictionaryOfString()
+ {
+ var input = new StringToStringIDictionaryWrapper(new Dictionary<string, string>
+ {
+ { "Name", "David" },
+ { "Job", "Software Architect" }
+ });
+
+ string json = JsonSerializer.ToString(input, typeof(IDictionary<string, string>));
+ Assert.Equal(@"{""Name"":""David"",""Job"":""Software Architect""}", json);
+
+ IDictionary<string, string> obj = JsonSerializer.Parse<IDictionary<string, string>>(json);
+ Assert.Equal(2, obj.Count);
+ Assert.Equal("David", obj["Name"]);
+ Assert.Equal("Software Architect", obj["Job"]);
+ }
+
[Theory]
[InlineData(typeof(ImmutableDictionary<string, string>), "\"headers\"")]
[InlineData(typeof(Dictionary<string, string>), "\"headers\"")]
public static void DeserializeUserDefinedDictionaryThrows()
{
string json = @"{""Hello"":1,""Hello2"":2}";
- Assert.Throws<NotSupportedException>(() => JsonSerializer.Parse<UserDefinedImmutableDictionary>(json));
+ Assert.Throws<NotSupportedException>(() => JsonSerializer.Parse<IImmutableDictionaryWrapper>(json));
}
public class ClassWithDictionaryButNoSetter
{
[JsonIgnore] public Dictionary<int, int> MyDictionary { get; set; }
}
-
- public class UserDefinedImmutableDictionary : IImmutableDictionary<string, int>
- {
- public int this[string key] => throw new NotImplementedException();
-
- public IEnumerable<string> Keys => throw new NotImplementedException();
-
- public IEnumerable<int> Values => throw new NotImplementedException();
-
- public int Count => throw new NotImplementedException();
-
- public IImmutableDictionary<string, int> Add(string key, int value)
- {
- throw new NotImplementedException();
- }
-
- public IImmutableDictionary<string, int> AddRange(IEnumerable<KeyValuePair<string, int>> pairs)
- {
- throw new NotImplementedException();
- }
-
- public IImmutableDictionary<string, int> Clear()
- {
- throw new NotImplementedException();
- }
-
- public bool Contains(KeyValuePair<string, int> pair)
- {
- throw new NotImplementedException();
- }
-
- public bool ContainsKey(string key)
- {
- throw new NotImplementedException();
- }
-
- public IEnumerator<KeyValuePair<string, int>> GetEnumerator()
- {
- throw new NotImplementedException();
- }
-
- public IImmutableDictionary<string, int> Remove(string key)
- {
- throw new NotImplementedException();
- }
-
- public IImmutableDictionary<string, int> RemoveRange(IEnumerable<string> keys)
- {
- throw new NotImplementedException();
- }
-
- public IImmutableDictionary<string, int> SetItem(string key, int value)
- {
- throw new NotImplementedException();
- }
-
- public IImmutableDictionary<string, int> SetItems(IEnumerable<KeyValuePair<string, int>> items)
- {
- throw new NotImplementedException();
- }
-
- public bool TryGetKey(string equalKey, out string actualKey)
- {
- throw new NotImplementedException();
- }
-
- public bool TryGetValue(string key, out int value)
- {
- throw new NotImplementedException();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- throw new NotImplementedException();
- }
- }
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+
+namespace System.Text.Json.Serialization.Tests
+{
+ public class IImmutableDictionaryWrapper : IImmutableDictionary<string, int>
+ {
+ public int this[string key] => throw new NotImplementedException();
+
+ public IEnumerable<string> Keys => throw new NotImplementedException();
+
+ public IEnumerable<int> Values => throw new NotImplementedException();
+
+ public int Count => throw new NotImplementedException();
+
+ public IImmutableDictionary<string, int> Add(string key, int value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IImmutableDictionary<string, int> AddRange(IEnumerable<KeyValuePair<string, int>> pairs)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IImmutableDictionary<string, int> Clear()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Contains(KeyValuePair<string, int> pair)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool ContainsKey(string key)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IEnumerator<KeyValuePair<string, int>> GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ public IImmutableDictionary<string, int> Remove(string key)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IImmutableDictionary<string, int> RemoveRange(IEnumerable<string> keys)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IImmutableDictionary<string, int> SetItem(string key, int value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IImmutableDictionary<string, int> SetItems(IEnumerable<KeyValuePair<string, int>> items)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryGetKey(string equalKey, out string actualKey)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryGetValue(string key, out int value)
+ {
+ throw new NotImplementedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class StringToObjectIDictionaryWrapper : IDictionary<string, object>
+ {
+ private readonly IDictionary<string, object> _dict;
+
+ public StringToObjectIDictionaryWrapper(IDictionary<string, object> dict)
+ {
+ _dict = dict;
+ }
+
+ public object this[string key] { get => _dict[key]; set => _dict[key] = value; }
+
+ public ICollection<string> Keys => _dict.Keys;
+
+ public ICollection<object> Values => _dict.Values;
+
+ public int Count => _dict.Count;
+
+ public bool IsReadOnly => false;
+
+ public void Add(string key, object value)
+ {
+ _dict.Add(key, value);
+ }
+
+ public void Add(KeyValuePair<string, object> item)
+ {
+ _dict.Add(item.Key, item.Value);
+ }
+
+ public void Clear()
+ {
+ _dict.Clear();
+ }
+
+ public bool Contains(KeyValuePair<string, object> item)
+ {
+ return _dict.Contains(item);
+ }
+
+ public bool ContainsKey(string key)
+ {
+ return _dict.ContainsKey(key);
+ }
+
+ public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
+ {
+ _dict.CopyTo(array, arrayIndex);
+ }
+
+ public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
+ {
+ return _dict.GetEnumerator();
+ }
+
+ public bool Remove(string key)
+ {
+ return _dict.Remove(key);
+ }
+
+ public bool Remove(KeyValuePair<string, object> item)
+ {
+ return _dict.Remove(item);
+ }
+
+ public bool TryGetValue(string key, out object value)
+ {
+ return _dict.TryGetValue(key, out value);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+
+ public class StringToStringIDictionaryWrapper : IDictionary<string, string>
+ {
+ private readonly IDictionary<string, string> _dict;
+
+ public StringToStringIDictionaryWrapper(IDictionary<string, string> dict)
+ {
+ _dict = dict;
+ }
+
+ public string this[string key] { get => _dict[key]; set => _dict[key] = value; }
+
+ public ICollection<string> Keys => _dict.Keys;
+
+ public ICollection<string> Values => _dict.Values;
+
+ public int Count => _dict.Count;
+
+ public bool IsReadOnly => false;
+
+ public void Add(string key, string value)
+ {
+ _dict.Add(key, value);
+ }
+
+ public void Add(KeyValuePair<string, string> item)
+ {
+ _dict.Add(item.Key, item.Value);
+ }
+
+ public void Clear()
+ {
+ _dict.Clear();
+ }
+
+ public bool Contains(KeyValuePair<string, string> item)
+ {
+ return _dict.Contains(item);
+ }
+
+ public bool ContainsKey(string key)
+ {
+ return _dict.ContainsKey(key);
+ }
+
+ public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
+ {
+ _dict.CopyTo(array, arrayIndex);
+ }
+
+ public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
+ {
+ return _dict.GetEnumerator();
+ }
+
+ public bool Remove(string key)
+ {
+ return _dict.Remove(key);
+ }
+
+ public bool Remove(KeyValuePair<string, string> item)
+ {
+ return _dict.Remove(item);
+ }
+
+ public bool TryGetValue(string key, out string value)
+ {
+ return _dict.TryGetValue(key, out value);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
<Compile Include="Serialization\Stream.ReadTests.cs" />
<Compile Include="Serialization\Stream.WriteTests.cs" />
<Compile Include="Serialization\TestClasses.cs" />
+ <Compile Include="Serialization\TestClasses.Dictionary.cs" />
<Compile Include="Serialization\TestClasses.Polymorphic.cs" />
<Compile Include="Serialization\TestClasses.SimpleTestClass.cs" />
<Compile Include="Serialization\TestClasses.SimpleTestClassWithNullables.cs" />