【问题标题】:How to Serialize/deserialize a nested dictionary of non-enum types with System.Text.Json?如何使用 System.Text.Json 序列化/反序列化非枚举类型的嵌套字典?
【发布时间】:2021-07-22 15:31:03
【问题描述】:

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

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# json dictionary jsonserializer system.text.json


【解决方案1】:

您正在为ResetableObjectTheme 的属性使用多态,而System.Text.Json 默认不支持多态。来自docs

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

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

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

如果您确实需要序列化和反序列化多态子类型,您将需要创建一个custom JsonConverter,如示例所示。 Is polymorphic deserialization possible in System.Text.Json?.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2019-05-31
    • 2017-04-10
    • 2011-01-15
    • 2011-06-03
    • 2014-08-10
    • 2014-02-19
    相关资源
    最近更新 更多