cc: @layomia,@ahsonkhan, @scalablecory, @steveharter
Related:
Description
Pull dotnet/corefx#39001 implemented by @layomia added support for serialization of types that implements natively supported collections without needing to create converters for them.
Unfortunately the implementation treats all derived types as the base type, so it's not possible to create specialized collections with converters. E.g. class MyCollection : List<int> gets treated as List<int>.
Specialized collections is necessary if the json has multiple ways of declaring a list, e.g.
{
"SpecialList" :
{
"Count": 2,
"Values" : [ 1, 2 ]
},
"NormalList" : [ 1, 2 ]
}
public class A
{
[JsonConverter(typeof(MyCollectionConverter))] // this is ignored and converter for List<int> is used instead
public MyCollection SpecialList { get; set; }
public List<int> NormalList { get; set }
}
[JsonConverter(typeof(MyCollectionConverter))] // this is ignored and converter for List<int> is used instead
public class MyCollection : List<int> { }
public class MyCollectionConverter : JsonConverter<MyCollection>
{
....
}
public class MyCollectionFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
// this only sees List<int>
}
}
public static void RunTest()
{
JsonSerializerOptions options = new JsonSerializerOptions
{
Converters =
{
new MyCollectionFactory(),
new MyCollectionConverter() // this is ignored and converter for List<int> is used
}
};
_ = JsonSerializer.Deserialize<A>("{}", options);
}
Expected priorities for getting the converter:
// Priority 1: attempt to get converter from JsonConverterAttribute on property.
// Priority 2: Attempt to get custom converter added at runtime.
// Priority 3: Attempt to get converter from [JsonConverter] on the type being converted.
// Priority 4: Attempt to get built-in converter.
Current behavior
// Priority 0: if type is derived from supported type, use converter for base type
// Priority 1: attempt to get converter from JsonConverterAttribute on property.
// Priority 2: Attempt to get custom converter added at runtime.
// Priority 3: Attempt to get converter from [JsonConverter] on the type being converted.
// Priority 4: Attempt to get built-in converter.
From JsonClassInfo.AddProperty [source]From JsonClassInfo.AddProperty source:
// Get implemented type, if applicable.
// Will return the propertyType itself if it's a non-enumerable, string, or natively supported collection.
Type implementedType = GetImplementedCollectionType(propertyType);
if (implementedType != propertyType)
{
jsonInfo = CreateProperty(implementedType, implementedType, implementedType, null, typeof(object), options);
}
else
{
jsonInfo = CreateProperty(propertyType, propertyType, propertyType, propertyInfo, classType, options);
}
In my example GetImplementedCollectionType(typeof(MyCollection)) will return List<int>.
I'm currently looking into it to see if I can find a fix.
--
Just found another bug: Since propertyInfo is ignored any JsonIgnoreAttribute will also be ignored.
e.g.
public class C
{
public int Version { get; set; }
[JsonIgnore] // this will be ignored
public MyCollection { get; set; }
}
cc: @layomia,@ahsonkhan, @scalablecory, @steveharter
Related:
Description
Pull dotnet/corefx#39001 implemented by @layomia added support for serialization of types that implements natively supported collections without needing to create converters for them.
Unfortunately the implementation treats all derived types as the base type, so it's not possible to create specialized collections with converters. E.g.
class MyCollection : List<int>gets treated asList<int>.Specialized collections is necessary if the json has multiple ways of declaring a list, e.g.
{ "SpecialList" : { "Count": 2, "Values" : [ 1, 2 ] }, "NormalList" : [ 1, 2 ] }Expected priorities for getting the converter:
Current behavior
From
JsonClassInfo.AddProperty[source]FromJsonClassInfo.AddPropertysource:In my example
GetImplementedCollectionType(typeof(MyCollection))will returnList<int>.I'm currently looking into it to see if I can find a fix.
--
Just found another bug: Since
propertyInfois ignored anyJsonIgnoreAttributewill also be ignored.e.g.