简体   繁体   English

如何为具有无效值的属性使用JSON.net的默认值

[英]How to use a default value for JSON.net for properties with invalid values

I am using the Newtonsoft JSON library to deserialize a response from a web service. 我正在使用Newtonsoft JSON库来反序列化来自Web服务的响应。 The problem is that some of the fields contain values which are not valid. 问题是某些字段包含无效的值。 For example, one field on one record contained a "T" for a field that is supposed to be numeric. 例如,一个记录上的一个字段包含一个应该是数字的字段的“T”。 What I would like to do is to have values for fields that are invalid be null, or some other default value. 我想要做的是使无效字段的值为null或其他一些默认值。 All of my properties are defined as nullable, so it is fine if they default to null. 我的所有属性都被定义为可空,因此如果它们默认为null则可以。

Is there a way to do this? 有没有办法做到这一点? I have tried creating custom JsonConverters, but I would prefer to not have to define a JsonConverter for each type. 我尝试过创建自定义JsonConverters,但我不想为每种类型定义JsonConverter。 If possible, I would like to, for all fields, set them null if the value for that property is not valid (like a "T" for a numeric type). 如果可能的话,我想,对于所有字段,如果该属性的值无效(如数字类型的“T”),则将它们设置为null。

I have looked at the OnError event handler, but that seems to discard a whole record on error. 我查看了OnError事件处理程序,但这似乎丢弃了整个错误记录。 I do not want to discard any records. 我不想丢弃任何记录。 I would just like for the value of invalid properties to be null. 我只想将无效属性的值设为null。

Is this possible? 这可能吗? I have looked a lot for answers and I did not find another question that was trying to do this, but please let me know if I overlooked an existing question. 我已经看了很多答案,我没有找到另一个试图做到这一点的问题,但如果我忽略了现有的问题,请告诉我。

Thank you for your help. 谢谢您的帮助。

You could make a JsonConverter for all nullable types that tries to deserialize the corresponding JSON value to the underlying type when non-null, and upon failure, returns null: 您可以为所有可空类型创建一个JsonConverter ,尝试在非null时将相应的JSON值反序列化为基础类型,并在失败时返回null:

public class NullableTypeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return Nullable.GetUnderlyingType(objectType) != null;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var underlyingType = Nullable.GetUnderlyingType(objectType);
        if (underlyingType == null)
            throw new JsonSerializationException("Invalid type " + objectType.ToString());
        var token = JToken.Load(reader);
        try
        {
            return token.ToObject(underlyingType, serializer);
        }
        catch (Exception ex)
        {
            // Log the exception somehow
            Debug.WriteLine(ex);
            return null;
        }
    }

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

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

Then use it when deserializing your classes. 然后在反序列化类时使用它

var settings = new JsonSerializerSettings { Converters = new[] { new NullableTypeConverter() } };

The converter will still throw an exception (from the call to JToken.Load() ) if the JSON itself is malformed and cannot be read. 如果JSON本身格式错误且无法读取,转换器仍将抛出异常(从调用JToken.Load() )。 It only swallows the exception if the JSON value cannot be converted to the appropriate type after being loaded. 如果在加载后无法将JSON值转换为适当的类型,它只会吞下异常。

Try setting the Error delegate on the Deserialize and handle the error you are looking for by setting args.ErrorContext.Handled = true. 尝试在反序列化上设置Error委托,并通过设置args.ErrorContext.Handled = true来处理您要查找的错误。 Check out the example code below: 看看下面的示例代码:

public class TestClass1
{
    public string Id { get; set; }
    public int Height { get; set; }
}

public class TestClass2
{
    public string Id { get; set; }
    public string Height { get; set; }
}

[TestMethod]
public void Test()
{
    TestClass2 x = new TestClass2() { Id = "1", Height = "something" };
    string str = JsonConvert.SerializeObject(x);

    JsonConvert.DeserializeObject<TestClass1>(str, new JsonSerializerSettings()
        {
            Error = delegate(object sender, ErrorEventArgs args)
            {
                if (args.ErrorContext.Error.GetType().FullName == typeof(JsonReaderException).FullName)
                    args.ErrorContext.Handled = true;
            }
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM