使用Json.net进行序列化时,如何根据类型更改属性名称? [英] How to change property names depending on the type when serializing with Json.net?

查看:151
本文介绍了使用Json.net进行序列化时,如何根据类型更改属性名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类型为object的属性,我必须根据其类型来更改名称.应该非常类似于 XML的[XmlElement("PropertyName", typeof(PropertyType))]属性.

I have a property of type object and I have to change the name depending on which type it has. Should be pretty similar to [XmlElement("PropertyName", typeof(PropertyType))] attribute for XML.

例如,我有一个属性public object Item { get; set; }

如果在运行时我的属性的类型为Vehicle,则要将属性的名称更改为"Vehicle";如果它的类型为Profile,我想将属性的名称更改为个人资料".

If at runtime my property has a type of Vehicle, I want to change the name of my property to "Vehicle"; if it has a type of Profile , I want to change the name of my property to "Profile".

推荐答案

没有内置的方法可以根据运行时类型动态更改属性的名称,但是您可以自定义

There is no built-in way to dynamically change the name of a property based on its runtime type, but you could make a custom JsonConverter coupled with a custom Attribute class to do what you want. The converter would need to be made to operate at the class level in order to be able to control the names of the properties written to JSON. It could iterate through the properties of the target class using reflection, and check if any property declared as object has the custom attribute applied. If it does and the object's runtime type matches the type specified in the attribute, then use the property name from the attribute, otherwise just use the original property name.

自定义属性如下所示:

[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]属性添加到包含要动态命名的一个或多个属性的目标类.然后,将自定义属性添加到该类中的一个或多个目标属性.您可以根据需要添加任意数量的属性,以涵盖所需的类型范围.

To use the converter, first add a [JsonConverter] attribute to the target class containing the property (or properties) that you want to be dynamically named. Then, add the custom attribute to the target property (or properties) in that class. You can add as many of the attribute as needed to cover the range of types you are expecting.

例如:

[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; }
}

然后,像往常一样进行序列化:

Then, serialize as you normally would:

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

这是一个有效的演示: https://dotnetfiddle.net/75HwrV

Here is a working demo: https://dotnetfiddle.net/75HwrV

这篇关于使用Json.net进行序列化时,如何根据类型更改属性名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆