首页 > 解决方案 > 如何使用 System.Text.Json 序列化/反序列化非枚举类型的嵌套字典?

问题描述

我正在尝试序列化这本字典:

IDictionary<string, ResetableObjectTheme> ResetableObjectThemes = new Dictionary<string, ResetableObjectTheme>()
{
    {"ThemeDark", new ResetableObjectTheme() { ResetablePatternObject = new PatternObject(), ResetableMaterialObject = new MaterialObject()}},
    {"ThemeLight", new ResetableObjectTheme() { ResetablePatternObject = new PatternObject(), ResetableMaterialObject = new MaterialObject()}},
};

string json = System.Text.Json.JsonSerializer.Serialize(ResetableObjectThemes, new JsonSerializerOptions() { WriteIndented = true });

之后,我得到一个错误的结果字符串 json,如下所示:

{
  "ResetableObjectThemes": {
    "ThemeDark": {
      "ResetablePatternObject": {},
      "ResetableMaterialObject": {}
    },
    "ThemeLight": {
      "ResetablePatternObject": {},
      "ResetableMaterialObject": {}
    }
  }
}

但它应该是这样的:

{
  "ResetableObjectThemes": {
    "ThemeDark": {
      "ResetablePatternObject": {
        "Thickness": 3,
        "BoundaryColor": {
          "ColorContext": null,
          "A": 255,
          "R": 0,
          "G": 0,
          "B": 128,
        },
      },
      "ResetableMaterialObject": {
        "BoundaryThickness": 3,
        "BoundaryColor": {
          "ColorContext": null,
          "A": 255,
          "R": 0,
          "G": 0,
          "B": 255,       
        },
      }
    },
    "ThemeLight": {
      "ResetablePatternObject": {
        "Thickness": 3,
        "BoundaryColor": {
          "ColorContext": null,
          "A": 255,
          "R": 0,
          "G": 0,
          "B": 128,
        },
      },
      "ResetableMaterialObject": {
        "BoundaryThickness": 3,
        "BoundaryColor": {
          "ColorContext": null,
          "A": 255,
          "R": 0,
          "G": 0,
          "B": 255,
        },
      }
    }
  }
}

这些课程是:

public class ResetableObjectTheme
{
    public ResetableBaseObject ResetablePatternObject { get; set; } = new PatternObject();
    public ResetableBaseObject ResetableMaterialObject { get; set; } = new MaterialObject();
}

public class PatternObject : ResetableBaseObject
{
    public double Thickness { get; set; } = 1;
    public Color BoundaryColor { get; set; } = Colors.Blue;
}
public class MaterialObject : ResetableBaseObject
{
    public double BoundaryThickness { get; set; } = 3;
    public Color BoundaryColor { get; set; } = Colors.Blue;
}

而 ResetableBaseObject 只是一个包含通用方法的基类。我已经将这种方法用于另一个东西,而不是类型 ResetableBaseObject,而是使用枚举并且序列化/反序列化工作得很好。使用字典的原因是这样我可以根据一些 UI 主题动态设置值:

ResetableObjectThemes[ThemeManager.CurrentTheme].ResetablePatternObject = new PatternObject() { Thickness = 5.5 };

为什么 System.Text.Json.JsonSerializer.Serialize/Deserialize 不能为嵌套的非枚举类型完成这项工作?

标签: c#jsondictionaryjsonserializersystem.text.json

解决方案


您正在对 的属性使用多态性ResetableObjectTheme,并且System.Text.Json默认情况下不支持多态性。从文档

支持多态类型层次结构的序列化。例如,如果一个属性被定义为接口或抽象类,那么即使运行时类型具有附加属性,也只会序列化接口或抽象类上定义的属性。
本节说明了此行为的例外情况...

绕过限制的最简单方法是将 的属性声明为ResetableObjectTheme适当的派生类型:

public class ResetableObjectTheme 
{ 
    public PatternObject ResetablePatternObject { get; set; } 
    public MaterialObject ResetableMaterialObject { get; set; } 
}

如果您确实需要序列化和反序列化多态子类型,则需要创建一个自定义JsonConverter,如System.Text.Json 中是否可以进行多态反序列化?.


推荐阅读