如何检查 JSON 中的值类型并决定是不是反序列化?
Posted
技术标签:
【中文标题】如何检查 JSON 中的值类型并决定是不是反序列化?【英文标题】:How to check the value type in a JSON and decide whether to deserialize?如何检查 JSON 中的值类型并决定是否反序列化? 【发布时间】:2022-01-12 13:04:42 【问题描述】:给定以下结构:
"meta":
"pagination":
"total": 378,
"count": 50,
"per_page": 50,
"current_page": 2,
"total_pages": 8,
"links":
"previous": "https://myapi.com.br/api/clients?page=1",
"next": "https://myapi.com.br/api/clients?page=3"
有时属性“links”的值作为空数组返回。
"meta":
"pagination":
"total": 14,
"count": 14,
"per_page": 50,
"current_page": 1,
"total_pages": 1,
"links": []
所以我创建了一个从 JsonConverter 继承的类型来设置在我的类属性中。 这是我不知道如何进行的地方。
public class LinksJsonConverter : JsonConverter
public override bool CanWrite => false;
public override bool CanConvert(Type objectType)
=> objectType == typeof(Links);
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
var links = new Links();
if (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.EndArray)
return links; // try return null
JObject jo = JObject.Load(reader);
links.Previous = jo["Previous"]?.ToString() ?? string.Empty;
links.Next = jo["Next"]?.ToString();?? string.Empty;
return links;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
=> ...
课程:
public class Links
public string Previous get; set;
public string Next get; set;
public class Pagination
public int Total get; set;
public int Count get; set;
[JsonProperty("per_page")]
public int PerPage get; set;
[JsonProperty("current_page")]
public int CurrentPage get; set;
[JsonProperty("total_pages")]
public int TotalPages get; set;
[JsonConverter(typeof(LinksJsonConverter))]
public Links Links get; set;
当我尝试从空的“链接”属性转换时出现错误。 当值为空数组时:
Message:
Test method IntegrationDownloaderServiceTests.ShouldProcessResultNfe threw exception:
Newtonsoft.Json.JsonSerializationException: Unexpected token when deserializing object:
EndArray. Path 'meta.pagination.links', line 123, position 17.
如何解决这种情况?
【问题讨论】:
显示您对链接的定义 只是为了确定:links
属性值可以是对象,也可以是数组(第一个结构中没有错字)?所以你的问题是如何反序列化类型未知的属性(可能是数组或对象?
@LaurentGabiot 是的,没错
当没有更多页面时,API 可能会将此值作为空数组返回。
【参考方案1】:
第一步将链接反序列化为对象:
public class Pagination
public int total get; set;
public int count get; set;
public int per_page get; set;
public int current_page get; set;
public int total_pages get; set;
public object links get; set;
public class Meta
public Pagination pagination get; set;
public class Root
public Meta meta get; set;
然后检查链接类型:(this)
public static class TypeExtensions
public static bool IsArrayOf<T>(this Type type)
return type == typeof (T[]);
并决定是否将对象转换为数组。
【讨论】:
IsArrayOf<T>(this Type type)
有点荒谬,您实际上并没有在这里检查links
,只是一些任意传递的类型变量。 IsArrayOf<T>(this object o)
(然后使用 typeof(o) == typeof(T[])
甚至只是 o is T[]
)更有意义。【参考方案2】:
我可能对我的问题不够清楚。 我想忽略数组值(至少现在),直到它有意义的那一天。 在这个 API 的文档中,我没有找到关于它的参考资料。 我会尝试联系开发者。
这样就成功了:
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.StartObject)
JObject jo = JObject.Load(reader);
var links = new Links
Previous = jo["previous"]?.Value<string>() ?? string.Empty,
Next = jo["next"]?.Value<string>() ?? string.Empty
;
return links;
else if (reader.TokenType == JsonToken.StartArray)
reader.Skip();
return null;
【讨论】:
以上是关于如何检查 JSON 中的值类型并决定是不是反序列化?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 ASP.NET 中的 json 反序列化基本类型(System.Runtime.Serialization.Json)