我有一个Newtonsoft JSON.NET的JsonConverter,可以帮助反序列化一个抽象类类型的属性。它的主要内容如下所示:
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
为空,则ReadJson
方法会在第一行出现JsonReaderException
错误:
'Newtonsoft.Json.JsonReaderException'类型的异常在Newtonsoft.Json.dll中发生,但在用户代码中未处理
附加信息:从JsonReader读取JObject时出错。当前JsonReader项不是对象:Null。路径'Pet',第1行,第11个位置。
我已经查看了自定义JsonConverter文档,但它仅涉及编写转换器。我尝试了以下操作:
if (reader.Value == null) return null; // this inverts the [Test] results
但是我得到了以下错误信息:
JsonSerializationException: 反序列化对象完成后,在JSON字符串中发现其他文本。
对于属性已经填充的情况。
简而言之,如何正确处理这种情况?
为了完整起见,这里提供一些单元测试,以展示手头的问题:
[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);
}
}
reader
没有正确的状态。因此,我结合了答案的解决方案和 [dbc] 的建议:if (reader.TokenType == JsonToken.Null) { JToken.Load(reader); return null; }
。 - JanDotNetreader.Value
是null
,尽管它实际上有一个值,因为初始标记是一个JsonToken.StartObject
,例如字面上的{
(它本身没有一个值)! - Bilal Akil