c# - 序列化后 Json.Net 属性名称更改
问题描述
假设我有一些我以前用 Json.Net 序列化过的类
public class BillingAddress
{
public string BillingCity { get; set; }
public string BillingState { get; set; }
public string BillingStreet { get; set; }
public string BillingZip { get; set; }
}
但是,我不得不返回并更改BillingStreet
为BillingStreet1
,然后再更改为BillingStreetA
。我正在尝试在 Json.Net 中找到一种方法来支持属性或自定义转换器,该转换器可以反序列化以前称为不同名称的属性,并且还支持具有多个不同的先前名称(例如在我的示例中) )。
我有一个依赖于属性的自定义转换器,如下所示:
[JsonVersionedPropertyName("BillingStreetA", "BillingStreet1")]
public string BillingStreet { get; set; }
public class VersionedPropertyNameConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
//return objectType.IsClass;
return (objectType == typeof(IPaymentMethod));
}
public override bool CanWrite
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object instance = objectType.GetConstructor(Type.EmptyTypes).Invoke(null);
PropertyInfo[] props = objectType.GetProperties();
var versionedProps = props.Where(x => Attribute.IsDefined(x, typeof(JsonVersionedPropertyName)));
JObject jo = JObject.Load(reader);
foreach (JProperty jp in jo.Properties())
{
foreach (var versProp in versionedProps)
{
var attrs = versProp.GetCustomAttributes(true);
foreach (var att in attrs)
{
var versionedProp = att as JsonVersionedPropertyName;
if (versionedProp != null)
{
var versions = versionedProp.VersionedNames;
PropertyInfo prop = props.FirstOrDefault(pi =>
pi.CanWrite && (string.Equals(pi.Name, jp.Name, StringComparison.OrdinalIgnoreCase) || versions.Contains(jp.Name)));
if (prop != null)
prop.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer));
}
}
}
}
return instance;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
但是,当我尝试将此转换器与另一个转换器一起使用时,我的整个反序列化都失败了。我试图弄清楚是否有更好的方法来做到这一点(版本化的属性名称)而不是我上面的方法。
解决方案
你很近。像这样的东西有效。我会把它作为一个练习来泛化它:):
public class OninaigConverter : JsonConverter
{
private readonly Dictionary<string, string> _propertyMappings = new Dictionary<string, string>
{
{"BillingStreetA", "BillingStreet"},
{"BillingStreet1", "BillingStreet"}
};
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType.GetTypeInfo().IsClass;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object instance = Activator.CreateInstance(objectType);
var props = objectType.GetTypeInfo().DeclaredProperties.ToList();
JObject jo = JObject.Load(reader);
foreach (JProperty jp in jo.Properties())
{
if (!_propertyMappings.TryGetValue(jp.Name, out var name))
name = jp.Name;
PropertyInfo prop = props.FirstOrDefault(pi =>
pi.CanWrite && pi.GetCustomAttribute<JsonPropertyAttribute>().PropertyName == name);
prop?.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer));
}
return instance;
}
}
推荐阅读
- java - 写入属性文件
- javascript - 选择一个文本,把它加粗,然后保存粗体标签的位置,以便以后围绕这些相同的文本
- java - 使用 jason.simple 将用户定义的数据类型转换为 JSON 对象类型
- python - 我可以用不同的消息向不同的收件人发送不同的邮件吗
- excel - Delphi/Excel - 工作表未实例化
- python-3.x - URL 解码和反序列化失败
- ios - 是否可以获得 safari 或其他浏览器当前用于访问网站的当前 URL?
- php - 如何获取主机名以从外部连接而不是“本地主机”
- java - 将图像从表单加载到 RecyclerView
- c++ - 将一个 rapidjson 分配器拥有的内存移动到另一个分配器