我有一个带有JSON对象数组的流,该数组以两种不同的格式出现,但包含相同类型的数据,我想将这两种格式反序列化为相同类型,因此我的视图不需要为两种格式的数据定制逻辑。目前,我正在使用自定义JsonConverter处理此问题。
这是我的模型:[JsonObject]
[JsonConverter(typeof(MyCommonObjectJsonConverter))]
public class MyCommonObject {
// some common fields, e.g.
public String Id { get; set; }
public string Text { get; set; }
}
这是我的自定义JsonConverter:
public class MyCommonObjectJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// don't need to worry about serialization in this case, only
// reading data
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
MyCustomObject result;
if (IsFormatOne(jObject))
{
// the structure of the object matches the first format,
// so just deserialize it directly using the serializer
result = serializer.Deserialize<MyCustomObject>(reader);
}
else if (IsFormatTwo(jObject))
{
result = new MyCustomObject();
// initialize values from the JObject
// ...
}
else
{
throw new InvalidOperationException("Unknown format, cannot deserialize");
}
return result;
}
public override bool CanConvert(Type objectType)
{
return typeof(MyCustomObject).IsAssignableFrom(objectType);
}
// Definitions of IsFormatOne and IsFormatTwo
// ...
}
然而,当我反序列化第一种格式的对象时,我得到一个错误,说它不能加载jobobject,因为JsonReader有TokenType "EndToken"。我不知道为什么会发生这种情况,我正在加载的数据格式正确。对我应该注意什么有什么建议吗?
在读取MyCommonObject
时,您希望返回到默认的反序列化,但是:
- 对
JObject.Load(reader)
的调用已经使读取器超过了对象,正如您所观察到的,并且 - 调用
serializer.Deserialize<MyCustomObject>(reader)
无论如何都会导致无限递归。
ReadJson()
中不必要的递归的习惯方法是手动分配结果,然后调用serializer.Populate(jObject.CreateReader(), result)
。例如: public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
JObject jObject = JObject.Load(reader);
MyCommonObject result;
if (IsFormatOne(jObject))
{
result = (existingValue as MyCommonObject ?? (MyCommonObject)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator()); // Reuse existingValue if present
// the structure of the object matches the first format,
// so just deserialize it directly using the serializer
using (var subReader = jObject.CreateReader())
serializer.Populate(subReader, result);
}
else if (IsFormatTwo(jObject))
{
result = (existingValue as MyCommonObject ?? (MyCommonObject)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());
// initialize values from the JObject
// ...
}
else
{
throw new InvalidOperationException("Unknown format, cannot deserialize");
}
return result;
}
在编写此代码时发现,调用serializer.Deserialize<MyCustomObject>(reader)
再次递归到我的转换器中,此时阅读器将从加载到JObject中到达一个结束令牌,使TokenType等于EndToken。我应该更仔细地检查堆栈跟踪。现在我将为这两种格式编写自定义初始化逻辑,使我的模型类与格式无关。