我有一个Newtonsoft JSON.NET JsonConverter
来帮助反序列化类型为抽象类的属性。它的要点如下:在自定义JsonConverter的ReadJson方法中处理空对象
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; }
}
这反序列化Person
具有非空Pet
时工作正常。但是,如果Pet
为null,则与此第一行ReadJson
方法分解的JsonReaderException
:
类型的异常“Newtonsoft.Json.JsonReaderException”发生在Newtonsoft.Json.dll但没有处理用户代码
附加信息:从JsonReader读取JObject时出错。当前的JsonReader项目不是对象:空。路径“宠物”,1号线,位置11
我检查the Custom 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);
}
}
和/或你可以加载JSON作为'JToken'和检查' token.Type == JTokenType.Null'。虽然实际上你的解决方案似乎最好 – dbc
在我的情况下,'reader'在返回null时没有正确的状态。因此,我想出了答案的解决方案和[dbc]的建议的组合:'if(reader.TokenType == JsonToken.Null){JToken.Load(reader);返回null; }'。 – JanDotNet