这有点类似于JSON.net - field is either string or List
让我们说我在POCO类之下,需要将json字符串反序列化为该类型。
public class Movie
{
[JsonProperty("title")]
public List<string> Title { get; set; }
[JsonProperty("images")]
public List<Image> Images { get; set; }
[JsonProperty("actors")]
public List<Actor> Actors { get; set; }
[JsonProperty("directors")]
public List<Director> Directors { get; set; }
}
让我们说需要反序列化的json字符串如下
{
"title": "Movie title",
"images": [
{"url" : "http://www.url.com/img_3.jpg"},
{"url" : "http://www.url.com/img_4.jpg"}
],
"actors": [
{"name" : "Steven Berkoff"},
{"name" : "Nikolaj Coster-Waldau"},
{"name" : "Julie Cox"}
],
"directors": { "name" : "Simon Aeby" }
},
{
"title": "Movie title",
"images": {"url" : "http://www.url.com/img_3.jpg"},
"actors": {"name" : "Julie Cox"},
"directors": { "name" : "Simon Aeby" }
}
这里的问题甚至认为POCO期待一个导演,演员和图像的列表,json只有每种类型中的一个。尝试反序列化时会出错。
答案 0 :(得分:2)
为那些列表创建一个转换器,可以识别列表中是否有一个或多个项目并将其应用于您的属性:
public class SingleOrEnumerableJsonConverter<TEnumerable> : JsonConverter
where TEnumerable : IEnumerable
{
public override bool CanConvert(Type objectType)
{
return typeof(TEnumerable).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = serializer.Deserialize<JToken>(reader);
return ConvertObject(obj) ?? GetDefaultValue();
}
private object GetDefaultValue()
{
return Activator.CreateInstance<TEnumerable>();
}
private object ConvertObject(JToken obj)
{
try
{
return obj.ToObject<TEnumerable>();
}
catch (JsonSerializationException)
{
// try as an array of object
return new JArray { obj }.ToObject<TEnumerable>();
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
object serializableValue = GetSerializableValue((TEnumerable)value, serializer);
serializer.Serialize(writer, serializableValue);
}
private object GetSerializableValue(TEnumerable items, JsonSerializer serializer)
{
var arr = new JArray(items.Cast<object>()
.Select(item => JToken.FromObject(item, serializer))
);
return arr.Count > 1 ? arr : arr.SingleOrDefault();
}
}
public class Movie
{
[JsonProperty("title")]
[JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<string>>))]
public List<string> Title { get; set; }
[JsonProperty("images")]
[JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<Image>>))]
public List<Image> Images { get; set; }
[JsonProperty("actors")]
[JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<Actor>>))]
public List<Actor> Actors { get; set; }
[JsonProperty("directors")]
[JsonConverter(typeof(SingleOrEnumerableJsonConverter<List<Director>>))]
public List<Director> Directors { get; set; }
}