序列化后更改了Json.Net属性名称

时间:2018-06-20 21:41:45

标签: c# json json.net

让我们说我有一些我以前用Json.Net序列化的类

public class BillingAddress
{
    public string BillingCity { get; set; }
    public string BillingState { get; set; }
    public string BillingStreet { get; set; }
    public string BillingZip { get; set; }
}

但是,我不得不回过头来将BillingStreet更改为BillingStreet1,然后再次更改为BillingStreetA。我正在尝试在Json.Net中找到一种方法来支持属性或自定义转换器,该方法可以反序列化以前称为其他名称的属性,并且还支持具有多个不同的先前名称(例如在我的示例中) )。

我有一个依赖于以下属性的自定义转换器:

[JsonVersionedPropertyName("BillingStreetA", "BillingStreet1")]
public string BillingStreet { get; set; }



public class VersionedPropertyNameConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        //return objectType.IsClass;
        return (objectType == typeof(IPaymentMethod));
    }

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        object instance = objectType.GetConstructor(Type.EmptyTypes).Invoke(null);
        PropertyInfo[] props = objectType.GetProperties();
        var versionedProps = props.Where(x => Attribute.IsDefined(x, typeof(JsonVersionedPropertyName)));

        JObject jo = JObject.Load(reader);
        foreach (JProperty jp in jo.Properties())
        {
            foreach (var versProp in versionedProps)
            {
                var attrs = versProp.GetCustomAttributes(true);
                foreach (var att in attrs)
                {
                    var versionedProp = att as JsonVersionedPropertyName;
                    if (versionedProp != null)
                    {
                        var versions = versionedProp.VersionedNames;
                        PropertyInfo prop = props.FirstOrDefault(pi => 
                            pi.CanWrite && (string.Equals(pi.Name, jp.Name, StringComparison.OrdinalIgnoreCase) || versions.Contains(jp.Name)));
                        if (prop != null)
                            prop.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer));
                    }
                }
            }
        }

        return instance;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

但是,当我尝试将此转换器一起使用时,我的整个反序列化失败。我试图找出是否有更好的方法(版本号属性名称)代替上面的方法。

1 个答案:

答案 0 :(得分:1)

您已经关闭。像这样的作品。我将其作为练习归纳为:):

public class OninaigConverter : JsonConverter
{
    private readonly Dictionary<string, string> _propertyMappings = new Dictionary<string, string>
    {
        {"BillingStreetA", "BillingStreet"},
        {"BillingStreet1", "BillingStreet"}
    };

    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType.GetTypeInfo().IsClass;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        object instance = Activator.CreateInstance(objectType);
        var props = objectType.GetTypeInfo().DeclaredProperties.ToList();

        JObject jo = JObject.Load(reader);
        foreach (JProperty jp in jo.Properties())
        {
            if (!_propertyMappings.TryGetValue(jp.Name, out var name))
                name = jp.Name;

            PropertyInfo prop = props.FirstOrDefault(pi =>
                pi.CanWrite && pi.GetCustomAttribute<JsonPropertyAttribute>().PropertyName == name);

            prop?.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer));
        }

        return instance;
    }
}