Json.Net在使用我的JsonConverter之前自行进行转换 [英] Json.Net Is converting on its own before using my JsonConverter

查看:415
本文介绍了Json.Net在使用我的JsonConverter之前自行进行转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的WPF代码中,我正在使用Newtonsoft.Json将json反序列化到我的模型中.首先,我收到一个Json字符串('json'),然后将其解析为'message'. (我要反序列化的对象包装在json字符串的数据"字段中).

In my WPF code, I'm using Newtonsoft.Json to deserialize json into my models. First, I receive a Json string ('json') which I then parse into 'message'. (The object I want to deserialize is wrapped in a "data" field in the json string).

Activity message = JObject.Parse(json)["data"].ToObject<Activity>();

我的Activity类使用几个[JsonProperty]属性来生成其字段.其中之一是一个称为"ActivityType"的枚举.

My Activity class uses several [JsonProperty] attributes to generate its fields. One of them is an enum called 'ActivityType'.

[JsonProperty("type")]
[JsonConverter(typeof(ActivityTypeConverter))]
public ActivityType Type { get; set; }

public enum ActivityType {
    EmailOpen,
    LinkClick,
    Salesforce,
    Unsupported
};

public class ActivityTypeConverter : JsonConverter {

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var rawString = existingValue.ToString().ToLower();
        if (rawString.Contains("click"))
            return ActivityType.LinkClick;
        else if (rawString.Contains("salesforce"))
            return ActivityType.Salesforce;
        else if (rawString.Contains("email_open"))
            return ActivityType.EmailOpen;
        else
        {
            Console.WriteLine("unsupported " + rawString);
            return ActivityType.Unsupported;
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return !objectType.Equals(typeof(ActivityType));
    }

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

奇怪和令人沮丧的是,我知道具有类型":"email_open"的json对象正在反序列化为ActivityType.不受支持,即使我的转换器应该将它们反序列化为EmailOpen.​​

What's bizarre and frustrating is that json objects which I know have "type":"email_open" are being deserialized as ActivityType.Unsupported, even though my converter should be deserializing them as EmailOpen.

调试已显示出问题所在: json字段类型"会自动将"email_open"反序列化为EmailOpen ,然后通过我的转换器发送. (然后中断,因为我的条件检查下划线,而EmailOpen.ToString()没有下划线.)


所以我的问题是:为什么没有转换器就进行转换,如何停止?我只希望它仅使用我的转换器

Debugging has shown what the problem is: the json field "type" is automatically deserializing "email_open" as EmailOpen and then it is sent through my converter. (It breaks then because my conditional checks for an underscore, while EmailOpen.ToString() doesn't have one.)


So my question then is: Why is it converting without my converter and how do I stop it? I just want it to only use my converter

推荐答案

我认为您的转换器正在被调用-它只是无法正常工作.问题在于,您正在使用existingValue中的值,而不是从JsonReader reader中读取新值.但是第二个值是要反序列化的类中的预先存在的属性值,而不是正在读取的值.

I think your converter is being called -- it's just not working. The problem is that, rather than reading the new value from the JsonReader reader, you are using the value from the existingValue. But this second value is the pre-existing property value in the class being deserialized, not the value being read.

您需要按照Json.NET的

You need to load the value from the reader along the lines of Json.NET's StringEnumConverter. Here's a version that does that and also handles standard values of your enum by subclassing StringEnumConverter and passing the value read from the file to the base class for further processing:

public class ActivityTypeConverter : StringEnumConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
        Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType);

        if (reader.TokenType == JsonToken.Null)
        {
            if (!isNullable)
                throw new JsonSerializationException();
            return null;
        }

        var token = JToken.Load(reader);
        if (token.Type == JTokenType.String)
        {
            var rawString = ((string)token).ToLower();
            if (rawString.Contains("click"))
                return ActivityType.LinkClick;
            else if (rawString.Contains("salesforce"))
                return ActivityType.Salesforce;
            else if (rawString.Contains("email_open"))
                return ActivityType.EmailOpen;
        }

        using (var subReader = token.CreateReader())
        {
            while (subReader.TokenType == JsonToken.None)
                subReader.Read();
            try
            {
                return base.ReadJson(subReader, objectType, existingValue, serializer); // Use base class to convert
            }
            catch (Exception ex)
            {
                return ActivityType.Unsupported;
            }
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ActivityType);
    }
}

这篇关于Json.Net在使用我的JsonConverter之前自行进行转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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