使用RestSharp调用REST API获取resources值及JSON反序列化异常问题
问题根因定位
- 两个接口返回的
resources字段结构存在本质差异:- 首次请求的接口返回
resources为字符串数组,元素为纯设备ID字符串 - 二次请求的接口返回
resources为对象数组,元素为包含设备基础信息、关联策略列表的复杂嵌套对象
- 首次请求的接口返回
- 之前编写的强类型响应类错误将
Resources属性固定为字符串列表,反序列化遇到对象类型的数组元素时,就会抛出Newtonsoft.Json.JsonReaderException解析错误 - 之前通过
GetValue("resources").ToString取值的写法,本质是把整个数组的序列化结果直接转成字符串,因此才会得到带方括号、引号的["xxx"]结果,没有实际提取数组内的单个元素值。
修正实现方案
轻量取值实现(兼容两种接口结构)
这种写法不需要重复定义强类型类,适配灵活的JSON结构:
- 首次接口提取单设备ID的代码:
Dim raw_id As JObject = JObject.Parse(data_response_raw) ' 将resources节点转为JArray,取第一个元素的纯值 Dim resourceList = CType(raw_id("resources"), JArray) Dim targetDeviceId = resourceList(0).ToString() - 二次接口提取嵌套字段的代码:
Dim drObj = JObject.Parse(dr) Dim resourceList = CType(drObj("resources"), JArray) ' 取嵌套对象内的device_id值 Dim deviceId = resourceList(0)("device_id").ToString() ' 取嵌套对象内的第一条策略类型 Dim firstPolicyType = resourceList(0)("policies")(0)("policy_type").ToString()
强类型反序列化实现
如果需要保留强类型约束,不要用同一个根类适配两个结构不同的接口:
- 调用返回字符串数组
resources的接口时,定义对应匹配的响应类:Public Class SimpleDeviceApiResponse Public Property meta As PaginationMeta Public Property resources As List(Of String) Public Property errors As List(Of String) End Class - 调用返回嵌套对象
resources的接口时,定义匹配嵌套结构的响应类:Public Class ComplexDeviceApiResponse Public Property meta As BasicMeta Public Property resources As List(Of DeviceInfo) Public Property errors As List(Of String) End Class ' 对应resources数组内的设备对象结构 Public Class DeviceInfo Public Property device_id As String Public Property policies As List(Of PolicyInfo) Public Property meta As DeviceMeta End Class Public Class PolicyInfo Public Property policy_type As String Public Property policy_id As String Public Property applied As Boolean Public Property settings_hash As String Public Property assigned_date As String Public Property applied_date As String Public Property rule_groups As List(Of Object) End Class Public Class DeviceMeta Public Property version As String End Class - 若需要简化类定义、兼容两种接口结构,可直接将
Resources属性定义为JArray类型,反序列化后按需读取节点值即可,不需要对数组元素做固定类型约束。
注意:之前参考的示例代码中通过
jsonResult.Item("data")取节点的写法不匹配当前接口结构,当前接口的顶级节点为meta、resources、errors,不存在data节点,必然会触发运行时错误。
内容的提问来源于stack exchange,提问作者Daniel Schmitz
相关产品推荐
相关产品推荐

