在自定义JsonConverter的ReadJson方法中处理空对象 [英] Handling null objects in custom JsonConverter's ReadJson method

查看:334
本文介绍了在自定义JsonConverter的ReadJson方法中处理空对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Newtonsoft JSON.NET JsonConverter来帮助反序列化类型为抽象类的属性.要点如下:

I've got a Newtonsoft JSON.NET JsonConverter to help deserialize a property whose type is an abstract class. The gist of it looks like this:

public class PetConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Animal);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jsonObject = JObject.Load(reader);

        if (jsonObject["Lives"] != null) return jsonObject.ToObject<Cat>(serializer);
        if (jsonObject["StopPhrase"] != null) return jsonObject.ToObject<Parrot>(serializer);

        return null;
    }

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

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

这是它处理的类:

public abstract class Animal 
{ }

public class Cat : Animal
{
    public int Lives { get; set; }
}

public class Parrot : Animal
{
    public string StopPhrase { get; set; }
}

public class Person
{
    [JsonConverter(typeof(PetConverter))]
    public Animal Pet { get; set; }
}

当反序列化具有非空PetPerson时,此方法可以正常工作.但是,如果Pet为null,则ReadJson方法在第一行中断,并带有JsonReaderException:

This works fine when deserializing a Person that has a non-null Pet. But if the Pet is null, then the ReadJson method breaks on the first line with this a JsonReaderException:

Newtonsoft.Json.dll中发生了'Newtonsoft.Json.JsonReaderException'类型的异常,但未在用户代码中处理

An exception of type 'Newtonsoft.Json.JsonReaderException' occurred in Newtonsoft.Json.dll but was not handled in user code

其他信息:从JsonReader读取JObject时出错.当前JsonReader项不是对象:空.路径宠物",第1行,位置11.

Additional information: Error reading JObject from JsonReader. Current JsonReader item is not an object: Null. Path 'Pet', line 1, position 11.

我已经检查了自定义JsonConverter 文档,但这是仅关于 writing 转换器.我尝试了以下方法:

I've checked the Custom JsonConverter documentation, but it is merely about a writing converter. I've tried the following:

if (reader.Value == null) return null; // this inverts the [Test] results

但是我得到:

JsonSerializationException:对象反序列化完成后,在JSON字符串中发现了其他文本.

JsonSerializationException: Additional text found in JSON string after finishing deserializing object.

对于填充属性 的情况.

简而言之,处理这种情况的正确方法是什么?

In short, what is the proper way to handle this situation?

为完整起见,这里有一些单元测试可以说明问题所在:

For completeness, here are some unit tests that demonstrate the issue at hand:

[TestFixture]
public class JsonConverterTests
{
    [Test]
    public void Cat_survives_serialization_roundtrip()
    {
        var person = new Person { Pet = new Cat { Lives = 9 } };
        var serialized = JsonConvert.SerializeObject(person);
        var deserialized = JsonConvert.DeserializeObject<Person>(serialized);
        Assert.That(deserialized.Pet, Is.InstanceOf<Cat>());
        Assert.That((deserialized.Pet as Cat).Lives, Is.EqualTo(9));
    }

    [Test]
    public void Parrot_survives_serialization_roundtrip()
    {
        var person = new Person { Pet = new Parrot { StopPhrase = "Lorrie!" } };
        var serialized = JsonConvert.SerializeObject(person);
        var deserialized = JsonConvert.DeserializeObject<Person>(serialized);
        Assert.That(deserialized.Pet, Is.InstanceOf<Parrot>());
        Assert.That((deserialized.Pet as Parrot).StopPhrase, Is.EqualTo("Lorrie!"));
    }

    [Test]
    public void Null_property_does_not_break_converter()
    {
        var person = new Person { Pet = null };
        var serialized = JsonConvert.SerializeObject(person);
        var deserialized = JsonConvert.DeserializeObject<Person>(serialized);
        Assert.That(deserialized.Pet, Is.Null);
    }
}

推荐答案

在写问题时,特别是在写我尝试过的东西"时,我找到了一种可能的解决方案:

While writing the question, specifically while writing the "what have I tried" bit, I find one possible solution:

if (reader.TokenType == JsonToken.Null) return null;

我发布此消息有两个原因:

I'm posting this for two reasons:

  1. 如果足够好,可能会帮助其他人遇到相同的问题.
  2. 我可能会从其他人的答案中学到更好,更具竞争性的解决方案.

FWIW,这是完整的JsonConverter,用于对类型为抽象类的属性的反序列化进行非常基本的处理:

FWIW, here's the full JsonConverter for very basic handling deserialization of a property whose type is an abstract class:

public class PetConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Animal);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null) return null;

        JObject jsonObject = JObject.Load(reader);

        if (jsonObject["Lives"] != null) return jsonObject.ToObject<Cat>(serializer);
        if (jsonObject["StopPhrase"] != null) return jsonObject.ToObject<Parrot>(serializer);

        return null;
    }

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

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

这篇关于在自定义JsonConverter的ReadJson方法中处理空对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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