2017-06-15 54 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

相关问题