在自定义JsonConverter的ReadJson方法中处理空对象 [英] Handling null objects in custom JsonConverter's ReadJson method
问题描述
我有一个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; }
}
当反序列化具有非空Pet
的Person
时,此方法可以正常工作.但是,如果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:
- 如果足够好,可能会帮助其他人遇到相同的问题.
- 我可能会从其他人的答案中学到更好,更具竞争性的解决方案.
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屋!