我有一个这样的用例,并找到一种方法将json字符串反序列化为C#对象
Json数据如下detail
属性取决于type
属性
{
data: [
{
type: "A",
detail: {
property_a: "plan A"
}
},
{
type: "B",
detail: {
property_b: "plan B"
}
},
{
type: "A",
detail: {
property_a: "new"
}
}
]
}
C#模型
public class Results
{
[JsonProperty(PropertyName = "data")]
public List<Result> Data { get; set; }
}
public class Result
{
[JsonProperty(PropertyName = "type"]
public string Type { get; set; }
[JsonProperty(PropertyName = "detail"]
public Detail Detail { get; set; }
}
public class Detail
{
}
public class A: Detail
{
[JsonProperty(PropertyName = "property_a")]
public string PropertyA { get; set; }
}
public class B: Detail
{
[JsonProperty(PropertyName = "property_b")]
public string PropertyB { get; set; }
}
第一次尝试将json字符串反序列化为C#
var results = JsonConvert.DeserializeObject<Results>(jsonString);
// results.Data will contains 3 instances of Detail class, not A or B
// therefore, I cannot cast each of them to A or B for usage later.
然后,我尝试为Result类创建CustomCreationConverter
public class JsonConverter: CustomCreationConverter<Result>
{
public override SearchResult Create(Type objectType)
{
return new Result();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var result = new Result();
// loop through JSON string
while (reader.Read())
{
// return because it is now the end of object
if (reader.TokenType == JsonToken.EndObject)
return result;
if (reader.TokenType != JsonToken.PropertyName)
continue;
var propertyName = reader.Value.ToString();
if (!reader.Read())
return result;
if ("type".Equals(propertyName))
{
result.Type = reader.Value != null ? reader.Value.ToString() : null;
}
else if ("detail".Equals(propertyName))
{
// parse to instantiate A or B
switch (result.Type)
{
case "A":
result.Detail = serializer.Deserialize<A>(reader);
break;
case "B":
result.Detail = serializer.Deserialize<B>(reader);
break;
default:
break;
}
}
}
return result;
}
}
发生错误是因为serializer.Deserialize
再次开始读取第一个json令牌而无法创建A或B的实例。如何在此时继续解析以获取A和B的实例?想想案例类A和B仍然有很多属性,所以为它们编写自定义json转换器不是一个好的解决方案。
任何人都可以帮我解决方案和可视化代码,将上面的json字符串反序列化为Results对象吗?
我已经下载了Newtonsoft.Json的源代码进行调试,并找到了问题的根本原因。我误解了serializer.Deserialize
方法的逻辑。它有助于读取Json令牌并将对象构建为默认行为,因此没有问题。
为了解决这个问题,我添加了这行代码,以确保一旦json reader转到对象的末尾就返回Result对象。此对象将添加到列表中,下一个搜索对象将被反序列化...
// return because it is now the end of object
if (reader.TokenType == JsonToken.EndObject)
return result;