我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)
我可以使用此方法然后直接反序列化为正确的EBossApiResponse<T>
类型(如果为true,填充错误消息但保留.Data
属性== null),或反序列化到右侧List<EBossEntityType>
,创建一个新的EBossApiResponse<List<EBossEntityType>>
,并设置其.Data
属性.
然后我意识到这o.SelectToken("message")
将无法工作,因为o
它将是一个数组,而不是一个对象.可以.SelectToken()
采用表单的模式"[0].message"
来获取第一项的消息属性吗?
这个怎么样?
JObject o = JObject.Parse(response);
JArray arr = o as JArray;
return (arr != null && (JObject)arr[0].SelectToken("message") != null)
|| o.SelectToken("error") != null;
Run Code Online (Sandbox Code Playgroud)
或者我在完全错误的树上吠叫,对整个事情有一个更优雅的解决方案?
你至少可以代替JObject.Parse()
用JToken.Parse()
,因为JToken
是两个基类JObject
和JArray
.然后你可以检查结果是a JArray
还是a JObject
(或者可能是JValue
整数).
var result = JToken.Parse(response);
if (result is JArray)
{
// ...
}
else if (result is JObject)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)