通过使用自定义转换器,您将能够实现您所需要的。
以下基于属性的组件套件可能适合您的需求,并且非常通用,以防您想扩展它。
基础属性类
定义IsMatch,它允许您定义对象属性是否与 json 属性匹配。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public abstract class JsonDeserializationPropertyMatchAttribute : Attribute
{
protected JsonDeserializationPropertyMatchAttribute() { }
public abstract bool IsMatch(JProperty jsonProperty);
}
示例实现:多反序列化名称
定义一个属性,允许您将多个名称关联到一个属性。 IsMatch 实现简单地遍历它们并尝试找到匹配项。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class JsonDeserializationNameAttribute : JsonDeserializationPropertyNameMatchAttribute
{
public string[] PropertyNames { get; private set; }
public JsonDeserializationNameAttribute(params string[] propertyNames)
{
this.PropertyNames = propertyNames;
}
public override bool IsMatch(JProperty jsonProperty)
{
return PropertyNames.Any(x => String.Equals(x, jsonProperty.Name, StringComparison.InvariantCultureIgnoreCase));
}
}
转换器为了将这两个属性绑定到 json 反序列化,需要以下转换器:
public class JsonDeserializationPropertyMatchConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsClass;
}
public override bool CanWrite
{
get
{
return false;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var constructor = objectType.GetConstructor(new Type[0]);
if (constructor == null)
throw new JsonSerializationException("A parameterless constructor is expected.");
var value = constructor.Invoke(null);
var jsonObject = JObject.Load(reader);
var jsonObjectProperties = jsonObject.Properties();
PropertyInfo[] typeProperties = objectType.GetProperties();
var typePropertyTuples = new List<Tuple<PropertyInfo, Func<JProperty, bool>>>();
foreach (var property in typeProperties.Where(x => x.CanWrite))
{
var attribute = property.GetCustomAttribute<JsonDeserializationPropertyMatchAttribute>(true);
if (attribute != null)
typePropertyTuples.Add(new Tuple<PropertyInfo, Func<JProperty, bool>>(property, attribute.IsMatch));
else
typePropertyTuples.Add(new Tuple<PropertyInfo, Func<JProperty, bool>>(property, (x) => false));
}
foreach (JProperty jsonProperty in jsonObject.Properties())
{
var propertyTuple = typePropertyTuples.FirstOrDefault(x => String.Equals(jsonProperty.Name, x.Item1.Name, StringComparison.InvariantCultureIgnoreCase) || x.Item2(jsonProperty));
if (propertyTuple != null)
propertyTuple.Item1.SetValue(value, jsonProperty.Value.ToObject(propertyTuple.Item1.PropertyType, serializer));
}
return value;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
示例使用上面粘贴的代码,并通过如下装饰类,我设法让对象正确反序列化:
[JsonConverter(typeof(JsonDeserializationPropertyMatchConverter))]
public class Package
{
public string Carrier { get; set; }
[JsonDeserializationName("Tracking_Number","anotherName")]
public string TrackingNumber { get; set; }
}
输出 1
var input = "{ carrier: \"fedex\", trackingNumber: \"123123123\" }";
var output = JsonConvert.DeserializeObject<Package>(input); // output.TrackingNumber is "123123123"
输出 2
var input = "{ carrier: \"fedex\", tracking_Number: \"123123123\" }";
var output = JsonConvert.DeserializeObject<Package>(input); // output.TrackingNumber is "123123123"
输出 3
var input = "{ carrier: \"fedex\", anotherName: \"123123123\" }";
var output = JsonConvert.DeserializeObject<Package>(input); // output.TrackingNumber is "123123123"