我正在使用此调用从 JSON 中读取对象列表:
Rootobject userInfo = JsonConvert.DeserializeObject<Rootobject>(File.ReadAllText(strFileName));
但我得到一个异常(exception)
Cannot deserialize the current JSON array
.如果类对象之一中的数组之一为空。只要有数据,一切正常。下面是一个 JSON 的例子,它导致了反序列化器:
这是 Venue 对象的正常数据类型:
"venue": {
"venue_id": 696895,
"venue_name": "Blackfinn Ameripub",
"venue_slug": "blackfinn-ameripub",
"primary_category": "Food",
"parent_category_id": "4d4b7105d754a06374d81259",
"categories": {
"count": 1,
"items": [
{
"category_name": "American Restaurant",
"category_id": "4bf58dd8d48988d14e941735",
"is_primary": true
}
]
},
"is_verified": false
},
这是导致异常的原因,一个空数组:
"venue": [
],
我曾尝试使用
JsonSerializerSettings
选项包括 DefaultValueHandling
, NullValueHandling
和 MissingMemberHandling
但它们似乎都不能阻止错误。知道如何反序列化 JSON 并忽略数据中的任何空数组吗?我希望它可以处理任何空数组,而不仅仅是上面针对对象
Venue
的示例.New issue was found - 03/17/2018 <<
嗨,下面的转换器一直工作得很好,但是我从我的 json 响应中得到的服务器又提出了另一个挑战。 JSON.NET 检索此类数据没有问题:"toasts": { "total_count": 1, "count": 1, "auth_toast": false, "items": [ { "uid": 3250810, "user": { "uid": 3250810, "account_type": "user", "venue_details": [ ], "brewery_details": [ ] }, "like_id": 485242625, "like_owner": false, "created_at": "Wed, 07 Mar 2018 07:54:38 +0000" } ] },
特别是具有venue_details 的部分。 99% 的回复都以这种格式返回了venue_details:"venue_details": [ ],
但后来我突然得到了这种格式:"toasts": { "total_count": 1, "count": 1, "auth_toast": false, "items": [ { "uid": 4765742, "user": { "uid": 4765742, "account_type": "venue", "venue_details": { "venue_id": 4759473 }, "brewery_details": [ ], "user_link": "https://untappd.com/venue/4759473" }, "like_id": 488655942, "like_owner": false, "created_at": "Fri, 16 Mar 2018 16:47:10 +0000" } ] },
注意venue_details 现在有一个值并包含一个venue_id。
因此,venue_details 最终看起来像一个对象而不是一个数组。这最终给出了这个异常(exception):
JsonSerializationException:无法将当前 JSON 对象(例如 {"name":"value"})反序列化为类型“System.Collections.Generic.List`1[System.Object]”,因为该类型需要一个 JSON 数组(例如 [1, 2,3]) 以正确反序列化。
在提供的转换器代码中,该异常发生在旁边带有 *s 的这一行中:public abstract class IgnoreUnexpectedArraysConverterBase : JsonConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var contract = serializer.ContractResolver.ResolveContract(objectType); if (!(contract is JsonObjectContract)) { throw new JsonSerializationException(string.Format("{0} is not a JSON object", objectType)); } do { if (reader.TokenType == JsonToken.Null) return null; else if (reader.TokenType == JsonToken.Comment) continue; else if (reader.TokenType == JsonToken.StartArray) { var array = JArray.Load(reader); if (array.Count > 0) throw new JsonSerializationException(string.Format("Array was not empty.")); return existingValue ?? contract.DefaultCreator(); } else if (reader.TokenType == JsonToken.StartObject) { // Prevent infinite recursion by using Populate() existingValue = existingValue ?? contract.DefaultCreator(); *** serializer.Populate(reader, existingValue); *** return existingValue;
任何想法如何添加这个额外的处理来解释在 JSON 返回对象而不是数组之间的这种翻转?
谢谢,
瑞克
最佳答案
你的问题不是你需要忽略空数组。如果"items"
数组为空,就不会有问题:
"items": [],
相反,您的问题如下。 JSON standard支持两种类型的容器:
[
开头(左括号)并以 ]
结尾(右括号)。值由 ,
分隔(逗号)。 {
开头(左括号)并以 }
结尾(右括号)。 由于某种原因,服务器返回一个空数组代替空对象。如果 Json.NET 希望遇到 JSON 对象,但遇到 JSON 数组,则会抛出
Cannot deserialize the current JSON array
你看到的异常(exception)。您可能会考虑要求生成 JSON 的人修复其 JSON 输出,但与此同时,您可以使用以下转换器在反序列化对象时跳过意外数组:
public class IgnoreUnexpectedArraysConverter<T> : IgnoreUnexpectedArraysConverterBase
{
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
}
public class IgnoreUnexpectedArraysConverter : IgnoreUnexpectedArraysConverterBase
{
readonly IContractResolver resolver;
public IgnoreUnexpectedArraysConverter(IContractResolver resolver)
{
if (resolver == null)
throw new ArgumentNullException();
this.resolver = resolver;
}
public override bool CanConvert(Type objectType)
{
if (objectType.IsPrimitive || objectType == typeof(string))
return false;
return resolver.ResolveContract(objectType) is JsonObjectContract;
}
}
public abstract class IgnoreUnexpectedArraysConverterBase : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var contract = serializer.ContractResolver.ResolveContract(objectType);
if (!(contract is JsonObjectContract))
{
throw new JsonSerializationException(string.Format("{0} is not a JSON object", objectType));
}
do
{
if (reader.TokenType == JsonToken.Null)
return null;
else if (reader.TokenType == JsonToken.Comment)
continue;
else if (reader.TokenType == JsonToken.StartArray)
{
var array = JArray.Load(reader);
if (array.Count > 0)
throw new JsonSerializationException(string.Format("Array was not empty."));
return null;
}
else if (reader.TokenType == JsonToken.StartObject)
{
// Prevent infinite recursion by using Populate()
existingValue = existingValue ?? contract.DefaultCreator();
serializer.Populate(reader, existingValue);
return existingValue;
}
else
{
throw new JsonSerializationException(string.Format("Unexpected token {0}", reader.TokenType));
}
}
while (reader.Read());
throw new JsonSerializationException("Unexpected end of JSON.");
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后,如果空数组只能出现在对象图中的一处,您可以将转换器添加到您的模型中,如下所示:
public class Rootobject
{
[JsonConverter(typeof(IgnoreUnexpectedArraysConverter<Venue>))]
public Venue venue { get; set; }
}
但是,如果如您所说,任何对象都可能被空数组替换,则可以使用非泛型
IgnoreUnexpectedArraysConverter
对于所有对象类型:var resolver = new DefaultContractResolver(); // Cache for performance
var settings = new JsonSerializerSettings
{
ContractResolver = resolver,
Converters = { new IgnoreUnexpectedArraysConverter(resolver) },
};
var userInfo = JsonConvert.DeserializeObject<Rootobject>(jsonString, settings);
笔记:
TypeNameHandling
或 PreserveReferencesHandling
设置。 "items"
数组),请参阅 How to handle both a single item and an array for the same property using JSON.net . null
遇到数组时,修改如下:else if (reader.TokenType == JsonToken.StartArray)
{
var array = JArray.Load(reader);
if (array.Count > 0)
throw new JsonSerializationException(string.Format("Array was not empty."));
return existingValue ?? contract.DefaultCreator();
}
工作样本.Net fiddle .
关于json.net - 如何使用 JsonConvert.DeserializeObject 忽略空数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48791322/