我有一个自定义的 JsonConverter,我需要在其中更改某些属性的默认序列化和反序列化。查看反序列化:
我正在覆盖ReadJson
方法,如下所示:
while (reader.Read())
{
if (reader.TokenType == JsonToken.PropertyName)
{
var propertyName = reader.Value.ToString();
if (reader.Read())
{
...
然后,我可以检查令牌类型,并在适当的情况下执行我的自定义工作。这适用于大多数类型,但是如果我有一个可枚举的属性并且已序列化为 JsonArray,那么我想在继续我的自定义内容之前使用该属性的默认实现。
我该怎么做?
当读取器位于某个值时,您可以调用 JsonSerializer.Deserialize()
、 JToken.Load()
、 JArray.Load()
或 JObject.Load()
来反序列化或加载该值。 通常,我更喜欢这样做而不是进行手动"原子"读取,因为它可确保正确处理嵌套,并使读取器正确定位JSON流中的下一项。 在定位在属性值上时,使用适当的类型调用JsonSerializer.Deserialize
可提供该属性反序列化的默认实现。
实际上,编写ReadJson
方法的一种简单方法是将对象的全部内容加载到JObject
中,然后循环访问属性:
var obj = JObject.Load(reader);
foreach (var property in obj.Properties())
{
switch (property.Name)
{
case "Data2":
{
// For example
myClass.Data2 = obj.ToObject<List<double>>(serializer);
}
break;
// More cases as necessary
default:
Debug.WriteLine("Unknown property " + property);
break;
}
}
如果出于某种原因您不想这样做,您可以逐个属性读取并反序列化或加载单个值:
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
if (reader.TokenType == JsonToken.PropertyName)
{
var propertyName = reader.Value.ToString();
if (reader.Read())
{
switch (propertyName)
{
case "Data1":
{
// Expecting a double value.
if (reader.TokenType == JsonToken.Integer || reader.TokenType == JsonToken.Float)
myClass.Data1 = Convert.ToDouble(reader.Value);
else
{
// Unknown value, skip or throw an exception
JToken.Load(reader);
}
}
break;
case "Data2":
{
// For example
myClass.Data2 = serializer.Deserialize<List<double>>(reader);
}
break;
case "Data3":
{
// Expecting a string value.
myClass.Data3 = JToken.Load(reader).ToString();
}
break;
default:
{
// Unknown property, skip or throw an exception
var unknownValue = JToken.Load(reader);
Debug.WriteLine(string.Format("Uknown property "{0}" with value: {1}", propertyName, unknownValue));
}
break;
}
}
}
}