[英]Use different name for serializing and deserializing with Json.Net
我从 Web API 接收 JSON 数据,如下所示:
[
{
"id": 1
"error_message": "An error has occurred!"
}
]
我将此数据反序列化为以下类型的对象:
public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}
稍后在我的应用程序中,我想再次将 ErrorDetails 对象序列化为 JSON,但使用属性名称ErrorMessage
而不是error_message
。 所以结果应该是这样的:
[
{
"Id": 1
"ErrorMessage": "An error has occurred!"
}
]
有没有一种简单的方法可以使用 Json.Net 完成此任务? 也许使用自定义解析器和一些属性,如:
public class ErrorDetails
{
public int Id { get; set; }
[SerializeAs("ErrorMessage")]
[DeserializeAs("error_message")]
public string ErrorMessage { get; set; }
}
但是解析器不会告诉我何时序列化或反序列化。
您可以使用JsonSerializerSettings
、 ContractResolver 和 NamingStrategy 。
public class ErrorDetails
{
public int Id { get; set; }
public string ErrorMessage { get; set; }
}
var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
对于去序列化,您可以使用SnakeCaseNamingStrategy
。
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
要再次序列化对象,您不必更改JsonSerializerSettings
因为默认情况下将使用属性名称。
var jsonNew = JsonConvert.SerializeObject(obj);
jsonNew = "{'Id': 1,'ErrorMessage': '发生错误!'}"
或者您可以创建一个合同解析器,它可以决定使用哪个名称。 然后,您可以决定何时反序列化和序列化是要使用 pascal 大小写名称格式还是带下划线的格式。
public class CustomContractResolver : DefaultContractResolver
{
public bool UseJsonPropertyName { get; }
public CustomContractResolver(bool useJsonPropertyName)
{
UseJsonPropertyName = useJsonPropertyName;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (!UseJsonPropertyName)
property.PropertyName = property.UnderlyingName;
return property;
}
}
public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}
var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
var serializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CustomContractResolver(false)
};
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(true)
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
var jsonNew = JsonConvert.SerializeObject(obj, serializerSettings);
jsonNew = "{'Id': 1,'ErrorMessage': '发生错误!'}"
在序列化与反序列化时获得不同属性名称的另一种方法是使用ShouldSerialize
方法: https : ShouldSerialize
文档说:
要有条件地序列化属性,请添加一个方法,该方法返回与该属性同名的布尔值,然后在方法名称前加上
ShouldSerialize
。 方法的结果决定了属性是否被序列化。 如果该方法返回 true 则该属性将被序列化,如果它返回 false 则该属性将被跳过。
例如:
public class ErrorDetails
{
public int Id { get; set; }
// This will deserialise the `error_message` property from the incoming json into the `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get; set; }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
// The serialised output will return `ErrorMessage` with the value from `GetErrorMessage` i.e. `error_message` in the original json
public string ErrorMessage { get { return GetErrorMessage; } }
}
这会导致稍微更多的开销,所以如果处理大量属性或大量数据但对于小有效负载,请小心,如果你不介意稍微弄乱你的 DTO 类,那么这可能是一个比编写自定义更快的解决方案合约解析器等
我喜欢@lee_mcmullen 的答案,并在我自己的代码中实现了它。 现在我想我找到了一个稍微整洁的版本。
public class ErrorDetails
{
public int Id { get; set; }
// This will deserialise the `error_message` property from the incoming json and store it in the new `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get { return ErrorMessage; } set { ErrorMessage = value; } }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
// The serialised output will return `ErrorMessage` with the value set from `GetErrorMessage` i.e. `error_message` in the original json
public string ErrorMessage { get; set; }
}
我更喜欢这个的原因是在更复杂的模型中它允许继承同时保持所有“旧”自定义东西分开
public class ErrorDetails
{
public int Id { get; set; }
public string ErrorMessage { get; set; }
}
// This is our old ErrorDetails that hopefully we can delete one day
public class OldErrorDetails : ErrorDetails
{
// This will deserialise the `error_message` property from the incoming json and store it in the new `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get { return ErrorMessage; } set { ErrorMessage = value; } }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.