我正在使用Json.Net库(用于.NET v3.5)来处理来自EBoss CRM API的响应的反序列化。据我所知,API文档相当不稳定,因此我不得不自己动手来看看可以引出什么样的响应。
我希望有一个包装类EBossApiResponse<T>
,它将为API发回的任何错误消息提供属性,以及包含T
类型的反序列化数据的属性(将限制为一个抽象基类,它充当我为模拟返回数据而创建的任何类的基础类型。)
我最初的戳戳揭示了第一个问题。有效请求可以返回一组对象,例如:https://ebosscrm.com/api.php/job_type.json
这很容易反序列化为假设的T
List<EBossJobType>
。请注意,结果中没有错误属性。
对同一端点的格式错误的请求会返回不同的内容:https://ebosscrm.com/api.php/job_type.json?search[foo]=1
在这种情况下,返回一个数组,其中包含一个具有名为message
的单个属性的对象。
(注意,有些名为search[something]
的参数有效,但foo
永远不是有效的something
)
还有可能返回显式错误。在我看来,API正在捕获异常并格式化包含调试信息的JSON响应:https://ebosscrm.com/api.php/candidates.json?uid=114&api_key=f34js3kj
在这种情况下,返回的JSON不是数组,而是单个对象。我不确定如何迎合这些不同的响应结构。我最初的想法是拥有类似的东西:
protected bool IsNonDataResponse(string response)
{
JObject o = JObject.Parse(response);
return o.SelectToken("message") != null || o.SelectToken("error") != null;
}
我可以使用此方法然后直接反序列化为正确的EBossApiResponse<T>
类型(如果为true,填充错误消息但保留.Data
属性== null),或反序列化到右侧{{ 1}},创建一个新的List<EBossEntityType>
,并设置其EBossApiResponse<List<EBossEntityType>>
属性。
然后我意识到.Data
将不起作用,因为o.SelectToken("message")
将是一个数组,而不是一个对象。可以o
采用.SelectToken()
形式的模式来获取第一个项目的消息属性吗?
这个怎么样?
"[0].message"
或者我在完全错误的树上吠叫,对整个事情有一个更优雅的解决方案?
答案 0 :(得分:9)
您至少可以将JObject.Parse()
替换为JToken.Parse()
,因为JToken
是JObject
和JArray
的基类。然后,您可以检查结果是JArray
还是JObject
(或类似整数的JValue
)。
var result = JToken.Parse(response);
if (result is JArray)
{
// ...
}
else if (result is JObject)
{
// ...
}