2017-03-17 41 views
3

我有一個.Net Core Web API。它在模型屬性匹配請求主體時自動映射模型。舉例來說,如果你有這樣的類:將對象綁定到Web API端點時指定自定義屬性名稱

public class Package 
{ 
    public string Carrier { get; set; } 
    public string TrackingNumber { get; set; } 
} 

這將正確地將其綁定到一個POST端點如果請求體是以下JSON:

{ 
    carrier: "fedex", 
    trackingNumber: "123123123" 
} 

我需要做的就是指定自定義屬性映射。例如,使用上面的同一個類,如果TrackingNumber的值爲tracking_number,我需要能夠映射到JSON。

我該怎麼做?

回答

5

更改您的包類併爲您希望映射到不同json字段的每個字段添加JsonProperty裝飾。

public class Package 
{ 
    [JsonProperty(PropertyName = "carrier")] 
    public string Carrier { get; set; } 

    [JsonProperty(PropertyName = "trackingNumber")] 
    public string TrackingNumber { get; set; } 
} 
+0

[JsonProperty(屬性名= 「TRACKING_NUMBER」)] – Kalyan

0

通過使用自定義轉換器,你將能夠實現你所需要的。
基於屬性的以下組件套件可能適合您的需求,並且在需要擴展它時非常通用。

基本屬性類

定義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"