【问题标题】:Access already deserialized properties from JsonConverter.ReadJson从 JsonConverter.ReadJson 访问已经反序列化的属性
【发布时间】:2020-01-31 11:47:34
【问题描述】:

我试图在反序列化旧 json 时解决向后兼容性问题。以前有double 属性,现在改为自定义类型。

我的想法是阅读 double 并使用自定义 json 转换器简单地转换它。

以前是:

public class A
{
    [JsonProperty)]
    string Name { get; set; }
    [JsonProperty)]
    double Value { get; set; }
}

序列化为

{"Name":"test","Value":33.0}

新的:

public class A
{
    [JsonProperty]
    [JsonConverter(typeof(MyJsonConverter))]
    public MyType Value { get; set; }
}

序列化为

{"Value":{"Value":33.0,"Name":"test", ...}},

转换器:

public class MyJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => true;

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value is double value)
            return new MyType(value, ???); // here is the problem, I need Name value here
        return reader.Value;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>
        JToken.FromObject(value).WriteTo(writer);
}

但要构造MyType,我需要字符串参数,它是另一个属性Name的值

如何从转换器访问Name 值以获取Value?如何访问任何已反序列化的内容?有没有什么树?令牌树?

另一件事:在WriteJson 方法中我想做“没什么”特别的,我的实现是否正确?或者有没有一种简单的方法可以防止转换器在序列化时做任何“特殊”的事情?

【问题讨论】:

    标签: c# json.net jsonconverter


    【解决方案1】:

    您需要将转换器应用于您的父 A 类:

    [JsonConverter(typeof(MyJsonConverter))]
    public class A
    {
        public MyType Value { get; set; }
    }
    
    public class AConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType) => objectType == typeof(A);
    
        public override bool CanWrite => false;
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject jObject = JObject.Load(reader);
    
            // Check if the keys contains "Name"
            string name = jObject["Name"]?.ToString();
    
            var a = new A();
    
            if (name != null)
            {
                a.Value = new MyType
                {
                    Name = name,
                    Value = jObject["Value"].Value<double>()
                };
            }
            else
            {
                a.Value = jObject["Value"].ToObject<MyType>();
            }
    
            return a;
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    要使用默认序列化,只需用false 覆盖CanWrite

    【讨论】:

    • 好主意,谢谢。我错过了CanWrite 属性。 CanConvert 检查真的需要吗?它从未被调用过。
    • @Sinatr 不是,但它被标记为abstract,因此需要被覆盖。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 2015-12-27
    • 2011-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    相关资源
    最近更新 更多