如何使用 System.Text.Json 序列化/反序列化非枚举类型的嵌套字典?
Posted
技术标签:
【中文标题】如何使用 System.Text.Json 序列化/反序列化非枚举类型的嵌套字典?【英文标题】:How to Serialize/deserialize a nested dictionary of non-enum types with 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 不能为嵌套的非枚举类型完成这项工作?
【问题讨论】:
System.Text.Json
不序列化派生类的属性。这是记录在案的行为,请参阅Why does System.Text Json Serialiser not serialise this generic property but Json.NET does?。如果要序列化和反序列化类层次结构,则需要创建自定义转换器,请参阅Is polymorphic deserialization possible in System.Text.Json?。事实上,我认为这是两者的重复,同意吗?
另外,您可以通过声明 declare public class ResetableObjectTheme public PatternObject ResetablePatternObject get; set; public MaterialObject ResetableMaterialObject get; set;
来消除序列化和反序列化类层次结构的要求
@dbc 是的,你是对的。只是修改了属性类型。谢谢。
【参考方案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?.
【讨论】:
以上是关于如何使用 System.Text.Json 序列化/反序列化非枚举类型的嵌套字典?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 System.Text.Json 序列化/反序列化非枚举类型的嵌套字典?
如何让 System.Text.Json 将对象反序列化为其原始类型?
缺少属性时如何强制 System.Text.Json 序列化程序抛出异常?
如何将类字段与 System.Text.Json.JsonSerializer 一起使用?
如何反序列化作为 System.Text.Json 中的字符串的嵌套 JSON 对象?
如何使用 System.Text.Json 将 json 字符串或流反序列化到 Dictionary<string,string>