【发布时间】:2021-11-27 00:29:04
【问题描述】:
我的问题与此类似:How to ignore JsonProperty(PropertyName = "someName") when serializing json? 其中的解决方案对我有用,但我很想知道是否可以使用更多属性扩展[JsonProperty] 属性(使用 Newtonsoft.json)?
一些背景:
我有一个应用程序(我们称之为 SmartModel),它根据用户输入在 c# 中生成物理模型。 SmartModel 由许多具有许多属性的类组成(例如,Pipe 类具有诸如Length、Diameter 等属性)。 SmartModel 写出一个 json 类型的 DTO,用于在单独的应用程序中进行求解(我们称之为 Solver 和 DTO,SolverDTO)。但是,除了这个 SmartModel 还写了一个不同的 DTO 用于保存和打开目的(方便地称为 SmartModelDTO)。
在这方面,在SmartModel中的某些属性之上有一个装饰器(例如[JsonProperty(SolverPropertyName = "someName")])会很方便,然后设置一个合约解析器来序列化和写出(以json格式):
- 生成 SolverDTO 时的
SolverPropertyName和 - 生成 SmartModelDTO 时的
UnderlyingName
(其中UnderlyingName默认已经是JsonProperty的属性,SolverPropertyName是JsonProperty应该扩展的属性)。
编辑
这里有一个最小的代码示例来解释我想要实现的目标:
我有一个名为Pipe 的示例类,如下所示:
class Pipe
{
[JsonProperty(PropertyName = "z_axis_dimension")]
public double Length { get; set; }
[JsonProperty(PropertyName = "cross_sectional_dimension")]
public double Diameter { get; set; }
}
我想以两种不同的方式进行序列化(将来可能会更多)。对于 SmartModelDTO,我希望序列化程序使用 UnderlyingProperty,但对于 SolverDTO,我希望在 JsonProperty 属性中使用 PropertyName。为此,可以实现以下合约解析器:
class IgnoreJsonPropertyNameContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization)
{
IList<JsonProperty> list = base.CreateProperties(
type,
memberSerialization);
foreach (JsonProperty prop in list)
{
prop.PropertyName = prop.UnderlyingName;
}
return list;
}
}
使用示例如下:
// Instance of Pipe:
Pipe pipe = new()
{
Length = 10.2,
Diameter = 5.5,
};
// Set some Json serializer settings:
JsonSerializerSettings jsonSerializerSettings = new();
jsonSerializerSettings.Formatting = Formatting.Indented;
// Serialize Pipe where property values are obtained from the
// JsonProperty PropertyName:
string solverJsonString = JsonConvert.SerializeObject(
pipe, jsonSerializerSettings);
Console.WriteLine($"Serialized string for SolverDTO:");
Console.WriteLine($"{solverJsonString}");
Console.WriteLine();
// Set a new contract resolver to return the
// JsonProperty UnderlyingName instead of the PropertyName:
jsonSerializerSettings.ContractResolver =
new IgnoreJsonPropertyNameContractResolver();
// Serialize Pipe where property values are obtained from the
// JsonProperty UnderlyingName:
string smartModelJsonString = JsonConvert.SerializeObject(
pipe, jsonSerializerSettings);
Console.WriteLine($"Serialized string for SmartModelDTO:");
Console.WriteLine($"{smartModelJsonString}");
Console.ReadLine();
给出以下输出:
Serialized string for SolverDTO:
{
"z_axis_dimension": 10.2,
"cross_sectional_dimension": 5.5
}
Serialized string for SmartModelDTO:
{
"Length": 10.2,
"Diameter": 5.5
}
但是,我想在Pipe 中有一个功能来标记属性,例如如下:
class Pipe
{
[JsonProperty(
SolverPropertyName = "z_axis_dimension",
APIPropertyName = "distance")]
public double Length { get; set; }
[JsonProperty(
SolverPropertyName = "cross_sectional_dimension",
APIPropertyName = "diameter")]
public double Diameter { get; set; }
}
然后设置与上面类似的不同的合约解析器来序列化Pipe对象,但一个使用SolverPropertyName序列化,另一个用于APIPropertyName,等等......
[JsonProperty] 类可以扩展吗?除了PropertyName之外还有SolverPropertyName、APIPropertyName等属性?
【问题讨论】:
-
除了描述您的代码,您能给我们提供具有预期输入/输出的实际代码吗?最好尽可能小,即minimal reproducible example
-
@DavidG。肯定的事。我用文字解释它,因为我上面提到的帖子也以类似的方式解释它并得到了一些答案。然而,我现在的位置已经很晚了,我会在天亮时发布一个最小的样本。问候。
-
@DavidG。我在上面添加了一个最小的可重现示例。
标签: c# json serialization properties attributes