首页 > 解决方案 > C# Newtonsoft.Json 忽略属性上的解析错误

问题描述

我被困在以不正确的格式解析 json。我从第三方收到 json,因此无法更改它。我想跳过格式不正确的属性并返回默认值。

假设我有一个只有一个整数属性MyIntAttribute的对象,但在实际场景中,我有更多不同类型的属性,这些属性可能不正确。

我有这个json:

        var json = @"[
            { ""MyIntAttribute"": 100 },
            { ""MyIntAttribute"": {
                ""wrongObject"": 1,
                ""help"": ""this is wrong""
            }}
        ]";

        var collection = JsonConvert.DeserializeObject<List<MyObject>>(json);

我的目标是收集两个对象。属性中的第一个值为 100,因为它在 json 中是正确的,第二个对象的默认值为 0,因为存在一些无意义的对象而不是整数值。

首先,我尝试在JsonSerializerSettings中使用错误处理,如下所示:

Error = (sender, args) => { args.ErrorContext.Handled = true; }

它会跳过所有错误,但不会创建具有默认值的对象。所以我最终只得到了一个对象,而第二个格式不正确的对象没有添加到集合中。

然后我尝试创建自定义转换器:

public class ParsingErrorConvertor : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

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

    public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
    {
        try
        {
            return serializer.Deserialize(reader, objectType);
        }
        catch (Exception e)
        {
            var t = objectType.IsValueType ? Activator.CreateInstance(objectType) : null;
            return t;
        }
    }

我的想法是将此转换器仅用于属性,如果出现问题,我想获得默认值,但我仍然缺少一些东西。

标签: c#jsonjson.net

解决方案


这是解决方案。

public class ErrorDefaultConvertor : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Object)
        {
            if (objectType.IsValueType) return Activator.CreateInstance(objectType);
            return null;
        }

        return token.ToObject(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

与属性一起使用。

    [JsonConverter(typeof(ErrorDefaultConvertor))]
    public int MyIntAttribute { get; set; }

推荐阅读