C# 序列化后Json.Net属性名称已更改
假设我有一个以前用Json.Net序列化过的类C# 序列化后Json.Net属性名称已更改,c#,json,json.net,C#,Json,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; } } 然而,我不得不返回并将Bill
public class BillingAddress
{
public string BillingCity { get; set; }
public string BillingState { get; set; }
public string BillingStreet { get; set; }
public string BillingZip { get; set; }
}
然而,我不得不返回并将BillingStreet
更改为BillingStreet 1
,然后再次更改为BillingStreet
。我试图在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();
}
}
但是,当我尝试将此转换器与另一个转换器一起使用时,我的整个反序列化失败。我正在试图找出是否有更好的方法(版本化的属性名)来代替上面的方法。你很接近了。像这样的东西很管用。我将把它作为一个练习来泛化:):
公共类oninagconverter:JsonConverter
{
private readonly Dictionary\u propertyMappings=新字典
{
{“BillingStreetA”,“BillingStreet”},
{“BillingStreet1”,“BillingStreet”}
};
公共覆盖boolcanwrite=>false;
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType.GetTypeInfo().IsClass;
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
对象实例=Activator.CreateInstance(objectType);
var props=objectType.GetTypeInfo().DeclaredProperties.ToList();
JObject jo=JObject.Load(读卡器);
foreach(jo.property()中的JProperty jp)
{
if(!\u propertyMappings.TryGetValue(jp.Name,out var Name))
name=jp.name;
PropertyInfo prop=props.FirstOrDefault(pi=>
pi.CanWrite&&pi.GetCustomAttribute().PropertyName==name);
prop?.SetValue(实例,jp.Value.ToObject(prop.PropertyType,序列化程序));
}
返回实例;
}
}
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;
}
}