如何使用 System.Text.Json Serialize/deserialize 非枚举类型的嵌套字典?
How to Serialize/deserialize a nested dictionary of non-enum types with 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,
},
}
}
}
}
class 是:
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 只是一个包含通用方法的基础 class。
我已经将这种方法用于其他东西,而不是类型 ResetableBaseObject,而是使用枚举并且 serialization/deserialization 工作得很好。
使用字典的原因是这样我可以根据一些 UI 主题动态设置值:
ResetableObjectThemes[ThemeManager.CurrentTheme].ResetablePatternObject = new PatternObject() { Thickness = 5.5 };
为什么 System.Text.Json.JsonSerializer.Serialize/Deserialize 无法完成嵌套的非枚举类型的工作?
您正在为 ResetableObjectTheme
的属性使用多态性,而 System.Text.Json
默认不支持多态性。来自 docs:
Serialization of a polymorphic type hierarchy is not supported. For example, if a property is defined as an interface or an abstract class, only the properties defined on the interface or abstract class are serialized, even if the runtime type has additional properties.
The exceptions to this behavior are explained in this section...
解决该限制的最简单方法是将 ResetableObjectTheme
的属性声明为适当的派生类型:
public class ResetableObjectTheme
{
public PatternObject ResetablePatternObject { get; set; }
public MaterialObject ResetableMaterialObject { get; set; }
}
如果您确实需要序列化和反序列化多态子类型,您将需要创建一个 custom JsonConverter
as shown in e.g. .
我正在尝试序列化这本词典:
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,
},
}
}
}
}
class 是:
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 只是一个包含通用方法的基础 class。 我已经将这种方法用于其他东西,而不是类型 ResetableBaseObject,而是使用枚举并且 serialization/deserialization 工作得很好。 使用字典的原因是这样我可以根据一些 UI 主题动态设置值:
ResetableObjectThemes[ThemeManager.CurrentTheme].ResetablePatternObject = new PatternObject() { Thickness = 5.5 };
为什么 System.Text.Json.JsonSerializer.Serialize/Deserialize 无法完成嵌套的非枚举类型的工作?
您正在为 ResetableObjectTheme
的属性使用多态性,而 System.Text.Json
默认不支持多态性。来自 docs:
Serialization of a polymorphic type hierarchy is not supported. For example, if a property is defined as an interface or an abstract class, only the properties defined on the interface or abstract class are serialized, even if the runtime type has additional properties.
The exceptions to this behavior are explained in this section...
解决该限制的最简单方法是将 ResetableObjectTheme
的属性声明为适当的派生类型:
public class ResetableObjectTheme
{
public PatternObject ResetablePatternObject { get; set; }
public MaterialObject ResetableMaterialObject { get; set; }
}
如果您确实需要序列化和反序列化多态子类型,您将需要创建一个 custom JsonConverter
as shown in e.g.