簡體   English   中英

如何使用Json.net序列化時根據類型更改屬性名稱?

[英]How to change property names depending on the type when serializing with Json.net?

我有一個object類型的object ,我必須根據它的類型更改名稱。 應該與XML的[XmlElement("PropertyName", typeof(PropertyType))]屬性非常相似。

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

如果在運行時我的屬性有一種類型的Vehicle ,我想將我的屬性名稱更改為“Vehicle”; 如果它有一種類型的Profile ,我想將我的屬性名稱更改為“配置文件”。

沒有基於其運行時類型動態更改屬性名稱的內置方法,但您可以使自定義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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM