我正在使用 VK API.有时服务器可以返回空数组而不是对象,例如:
I`m working with VK API. Sometimes server can return empty array instead of object, for example:
personal: [] //when it is empty
或
personal: {
religion: 'Нет',
smoking: 1,
alcohol: 4
} //when not empty.
我正在使用 JsonConvert.DeserializeObject 反序列化大部分 json,而这部分 json 使用
I`m deserializing most of json with JsonConvert.DeserializeObject, and this part of json with
MainObject = ((MainObject["response"].GetObject())["user"].GetObject())["personal"].GetObject();
try
{
Convert.ToByte(MainObject["political"].GetNumber();
}
catch {}
但是当它处理大量异常时,它会使应用程序运行缓慢.刚才我意识到这里还有一些字段可能在空时返回数组.我只是不知道如何快速清晰地完成它.有什么建议吗?
But it makes app works slowly when it`s handling a lot of exeptions. And just now i realised that here are some more fields that might return array when empty. I just have no ideas how to make it fastly and clearly. Any suggestions?
我的反序列化类(字段为空时不起作用):
My deserializing class (doen`t work when field is empty):
public class User
{
//some other fields...
public Personal personal { get; set; }
//some other fields...
}
public class Personal
{
public byte political { get; set; }
public string[] langs { get; set; }
public string religion { get; set; }
public string inspired_by { get; set; }
public byte people_main { get; set; }
public byte life_main { get; set; }
public byte smoking { get; set; }
public byte alcohol { get; set; }
}
另一个想法(不为空时不起作用):
Another idea (doesn`t work when not empty):
public List<Personal> personal { get; set; }
你可以制作一个 JsonConverter 如下所示,它查找指定类型的对象或空数组.如果是对象,它会反序列化该对象.如果是空数组,则返回null:
You could make a JsonConverter like the following, that looks for either an object of a specified type, or an empty array. If an object, it deserializes that object. If an empty array, it returns null:
public class JsonSingleOrEmptyArrayConverter<T> : JsonConverter where T : class
{
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override bool CanWrite { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var contract = serializer.ContractResolver.ResolveContract(objectType);
if (!(contract is Newtonsoft.Json.Serialization.JsonObjectContract || contract is Newtonsoft.Json.Serialization.JsonDictionaryContract))
{
throw new JsonSerializationException(string.Format("Unsupported objectType {0} at {1}.", objectType, reader.Path));
}
switch (reader.SkipComments().TokenType)
{
case JsonToken.StartArray:
{
int count = 0;
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.Comment:
break;
case JsonToken.EndArray:
return existingValue;
default:
{
count++;
if (count > 1)
throw new JsonSerializationException(string.Format("Too many objects at path {0}.", reader.Path));
existingValue = existingValue ?? contract.DefaultCreator();
serializer.Populate(reader, existingValue);
}
break;
}
}
// Should not come here.
throw new JsonSerializationException(string.Format("Unclosed array at path {0}.", reader.Path));
}
case JsonToken.Null:
return null;
case JsonToken.StartObject:
existingValue = existingValue ?? contract.DefaultCreator();
serializer.Populate(reader, existingValue);
return existingValue;
default:
throw new InvalidOperationException("Unexpected token type " + reader.TokenType.ToString());
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public static partial class JsonExtensions
{
public static JsonReader SkipComments(this JsonReader reader)
{
while (reader.TokenType == JsonToken.Comment && reader.Read())
;
return reader;
}
}
然后像这样使用它:
public class User
{
//some other fields...
[JsonConverter(typeof(JsonSingleOrEmptyArrayConverter<Personal>))]
public Personal personal { get; set; }
//some other fields...
}
您现在应该能够将用户反序列化到您的 User 类中.
You should now be able to deserialize a user into your User class.
注意事项:
转换器可以通过属性或在 中应用JsonSerializerSettings.Converters.
转换器不是为处理字符串等简单类型而设计的,它是为映射到 JSON 对象的类而设计的.那是因为它使用了 JsonSerializer.Populate() 避免读取过程中的无限递归.
The converter isn't designed to work with simple types such as strings, it's designed for classes that map to a JSON object. That's because it uses JsonSerializer.Populate() to avoid an infinite recursion during reading.
工作示例 .Net fiddles 这里和 这里.
Working sample .Net fiddles here and here.
这篇关于当值可以是对象或空数组时反序列化 JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!
读取 XML 时忽略空格Ignore whitespace while reading XML(读取 XML 时忽略空格)
带有检查空元素的 XML 到 LINQXML to LINQ with Checking Null Elements(带有检查空元素的 XML 到 LINQ)
在 C# 中读取带有未闭合标签的 XMLReading XML with unclosed tags in C#(在 C# 中读取带有未闭合标签的 XML)
在 C# 中使用 Html 敏捷性解析表格、单元格Parsing tables, cells with Html agility in C#(在 C# 中使用 Html 敏捷性解析表格、单元格)
使用 LINQ 从 xml 中删除元素delete element from xml using LINQ(使用 LINQ 从 xml 中删除元素)
解析格式错误的 XMLParse malformed XML(解析格式错误的 XML)