【问题标题】:Json.Net Is converting on its own before using my JsonConverterJson.Net 在使用我的 JsonConverter 之前自行转换
【发布时间】:2015-08-14 19:52:23
【问题描述】:

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

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

我的 Activity 类使用几个 [JsonProperty] 属性来生成它的字段。其中之一是一个名为“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();
    }
}

奇怪和令人沮丧的是,我知道具有 "type":"email_open" 的 json 对象被反序列化为 ActivityType.Unsupported,即使我的转换器应该将它们反序列化为 EmailOpen。​​

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


那么我的问题是:为什么没有我的转换器它会转换,我该如何阻止它?我只希望它只使用我的转换器

【问题讨论】:

  • 不应该是objectType.Equals(typeof(ActivityType)(前面没有!)吗? (或者只是objectType == typeof(ActivityType))?
  • @dbc 如果它已经是 ActivityType,我不希望它转换。那是我试图停止双重转换的尝试。 (没有改变任何东西,因为我发现,第一次转换甚至没有使用我的转换器)
  • 作为滚动您自己的转换器的替代方法,请参阅Howto decorate JSON.NET StringEnumConverter

标签: c# json wpf json.net deserialization


【解决方案1】:

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

您需要按照 Json.NET 的 StringEnumConverter 的行从读取器加载值。这是一个版本,它通过子类化StringEnumConverter 并将从文件中读取的值传递给基类进行进一步处理,从而处理枚举的标准值:

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

【讨论】:

  • 哦,我明白了,你是对的,我把existingValue 误认为是预转换的值。它可能是 EmailOpen,因为枚举是不可为空的,这是第一个选项(?)。无论如何,现在一切正常,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多