首页 > 解决方案 > C# 将 JSON 反序列化为依赖于类型属性的类

问题描述

假设我有这个小 json 片段:

{
  "Type": "Bar",
  "BarOnly": "This is a string readable when deserialized to the Bar class only, as declared in my type key"
}

我也有这三个类:

public class Base
{
    public enum SampleEnum
    {
        Bar,
        Baz,
    }

    public SampleEnum Type
    {
        get;
        set;
    }
}

public class Bar : Base
{
    public string BarOnly
    {
        get;
        set;
    }
}

public class Baz : Base
{
    public string BazOnly
    {
        get;
        set;
    }
}

基于 json 片段中的 Type 属性,我想让它反序列化为 Bar 或 Baz。
我的第一个想法是首先将其反序列化为 Base 类,然后使用其类型和 switch 语句将 JSON 再次反序列化为相应的类。(使用Newtonsoft.Json

var type = JsonConvert.DeserializeObject<Base>(json).Type;
string message = "";
switch (type)
{
    case (Base.SampleEnum.Bar):
        message = JsonConvert.DeserializeObject<Bar>(json).BarOnly;
        break;
    case (Base.SampleEnum.Baz):
        message = JsonConvert.DeserializeObject<Baz>(json).BazOnly;
        break;
}
Console.WriteLine(message);

不用说,这个过程非常多余、乏味,而且由于 switch 语句是硬编码的,因此根本不是很“动态”。
另一个想法是使用泛型类作为基类,并传入它应该反序列化到的实际类的类型,但是我最终得到了相同的 switch 语句来确定该类应该是什么。
由于您无法将枚举映射到类类型,因此我还考虑使用 Dictionary 将可能的枚举值映射到其对应的类;这仍然使映射过程硬编码。
有什么办法可以根据json对象的type属性动态获取要反序列化的相应类?

编辑:关于应该如何使用它以及如何获取数据似乎有些混乱;让我提供一些背景资料。
我正在遍历一个包含许多不同电子表格文件的目录,主要是 CSV 和 XML 文件。这些提要中的每一个都有一个“元文件”,描述如何处理它们的内容。这包括校验和、分隔符和其他信息。他们还声明其父文件的类型(CSV、XML 等)。因此,它们具有许多共同的属性(例如Base我的示例中的类),但也有自己的一组属性。它们派生自一个抽象类,该类要求它们实现一个函数,该函数返回相应的提要处理类的实例,并直接使用元类中的值进行初始化。我希望这是有道理的。

标签: c#jsonclassgenericstypes

解决方案


@OguzOzgul 评论是正确的。对于由需要序列化和反序列化的接口组成的对象,我已经做了无数次。

请参阅 Newtonsoft 的 TypeNameHandling: https ://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm

您的 json 文件看起来会略有不同:

{
    "$type": "SomeNamespace.Bar",
    "BarOnly": "This is a string readable when deserialized to the Bar class only, as declared in my type key"
}

如果你使用

new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
}

在序列化过程中,它将添加所有对象的完整类型名称,以确保 newtonsoft 在反序列化过程中知道它们的类型(假设您使用相同的设置)。这样您就不必为类型检测编写自己的自定义代码。


推荐阅读