反序列化 JSON 时,如何将声明为 IList<T> 的属性的具体类型配置为 ObservableCollection<T>?

问题描述 投票:0回答:1

我有一些类对我期望的 JSON 文件结构进行建模。对于 JSON 中的数组值,相应的属性被声明为具有不同类型

IList<T>
的类型
T
。我不控制这些课程。将 JSON 反序列化为根类型
MyClass
时,如何才能使我获得的类型
IList<T>
类的所有属性都使用具体类型
ObservableCollection<T>
构造?请注意
MyClass
具有
IList<T>
类型的深层嵌套属性。

希望下面的例子能更清楚地展示我的意图:

class MyClass{
    public IList<NestedClass> MyList { get; set; }
}

class NestedClass{
    public IList<AnotherNestedClass> NestedList { get; set; }
}

class AnotherNestedClass{
    // ... various properties.
}
var obj = JsonSerializer.Deserialize<MyClass>(jsonString);
Console.WriteLine(obj?.MyList?.GetType()); // This should be ObservableCollection<NestedClass>
c# json .net-core observablecollection system.text.json
1个回答
0
投票

您可以使用自定义

JsonConverterFactory
自动反序列化任何属性或值 declared as
IList<T>
as
ObservableCollection<T>

首先定义以下转换器工厂:

public class IListAsObservableCollectionConverter : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert) => 
        typeToConvert.IsInterface && typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(IList<>);
    
    public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => 
        (JsonConverter)Activator.CreateInstance(typeof(IListAsObservableCollectionConverterGeneric<>).MakeGenericType(typeToConvert.GetGenericArguments()))!;
    
    class IListAsObservableCollectionConverterGeneric<T> : JsonConverter<IList<T>>
    {
        public override void Write(Utf8JsonWriter writer, IList<T> value, JsonSerializerOptions options) =>
            JsonSerializer.Serialize(writer, value, value.GetType(), options);
        public override IList<T>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
            JsonSerializer.Deserialize<ObservableCollection<T>>(ref reader, options);
    }
}

然后使用以下选项反序列化:

var options = new JsonSerializerOptions
{
    Converters = { new IListAsObservableCollectionConverter() },
    // Other options as required
    IncludeFields = true, // Required to serialize & deserialize public fields as well as properties.
};
var obj = JsonSerializer.Deserialize<MyClass>(json, options);

演示小提琴在这里

© www.soinside.com 2019 - 2024. All rights reserved.