2017-06-15 114 views
2

我有一個object類型的屬性,我必須根據它具有的類型更改名稱。應該非常類似於XML的 [XmlElement("PropertyName", typeof(PropertyType))]屬性。如何在使用Json.net序列化時根據類型更改屬性名稱?

例如,我有一個屬性public object Item { get; set; }

如果在運行時我的財產的類型爲Vehicle,我想改變我的屬性設置爲「汽車」的名稱;如果它的類型爲Profile,我想將我的屬性名稱更改爲「配置文件」。

+2

能否請你擴大你的問題到[MCVE]顯示你想創建的JSON和你正在序列化的類型?見[問]。只要有這些信息,我們就會猜測你的問題是什麼。 – dbc

+0

Json.Net == Newtonsoft.Json - 沒有**或** –

+0

您是否在尋找[JsonPropertyAttribute](http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonPropertyAttribute.htm)? –

回答

5

沒有內置的方法根據其運行時類型動態更改屬性的名稱,但可以使用自定義JsonConverter加上自定義Attribute類來執行所需操作。爲了能夠控制寫入JSON的屬性的名稱,需要使轉換器在類級別上運行。它可以使用反射遍歷目標類的屬性,並檢查是否聲明爲object的任何屬性應用了自定義屬性。如果有,並且對象的運行時類型與屬性中指定的類型匹配,則使用該屬性的屬性名稱,否則只使用原始屬性名稱。

這裏的自定義屬性將是什麼樣子:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] 
class JsonPropertyNameByTypeAttribute : Attribute 
{ 
    public string PropertyName { get; set; } 
    public Type ObjectType { get; set; } 

    public JsonPropertyNameByTypeAttribute(string propertyName, Type objectType) 
    { 
     PropertyName = propertyName; 
     ObjectType = objectType; 
    } 
} 

這裏是轉換器的代碼:

public class DynamicPropertyNameConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     Type type = value.GetType(); 
     JObject jo = new JObject(); 

     foreach (PropertyInfo prop in type.GetProperties().Where(p => p.CanRead)) 
     { 
      string propName = prop.Name; 
      object propValue = prop.GetValue(value, null); 
      JToken token = (propValue != null) ? JToken.FromObject(propValue, serializer) : JValue.CreateNull(); 

      if (propValue != null && prop.PropertyType == typeof(object)) 
      { 
       JsonPropertyNameByTypeAttribute att = prop.GetCustomAttributes<JsonPropertyNameByTypeAttribute>() 
        .FirstOrDefault(a => a.ObjectType.IsAssignableFrom(propValue.GetType())); 

       if (att != null) 
        propName = att.PropertyName; 
      } 

      jo.Add(propName, token); 
     } 

     jo.WriteTo(writer); 
    } 

    public override bool CanRead 
    { 
     get { return false; } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     // ReadJson is not called if CanRead returns false. 
     throw new NotImplementedException(); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     // CanConvert is not called if a [JsonConverter] attribute is used 
     return false; 
    } 
} 

要使用轉換器,第一個[JsonConverter]屬性添加到目標類包含您想要動態命名的屬性(或屬性)。然後,將自定義屬性添加到該類中的目標屬性(或屬性)。您可以根據需要添加儘可能多的屬性,以涵蓋您期望的類型範圍。

例如:

[JsonConverter(typeof(DynamicPropertyNameConverter))] 
class Foo 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    [JsonPropertyNameByType("Vehicle", typeof(Vehicle))] 
    [JsonPropertyNameByType("Profile", typeof(Profile))] 
    public object Item { get; set; } 
} 

然後,序列化,你通常會:

string json = JsonConvert.SerializeObject(foo, Formatting.Indented); 

這裏是一個工作演示:https://dotnetfiddle.net/75HwrV

相關問題