2012-10-30 48 views
0

我使用Json.Net库(用于.NET v3.5)来处理来自EBoss CRM API的反应的反序列化。据我所见,API文档相当多,所以我不得不自己捅一下,看看可以引发什么样的反应。有条件的数组/对象反序列化与Json.Net

我想拥有一个包装类EBossApiResponse<T>,它将为API返回的任何错误消息提供属性,并且包含一个包含类型为T的反序列化数据的属性(它将被限制为一个抽象基类,我为建模返回的数据而创建的任何类的基础类型)。

我最初的戳说明了第一个问题。有效的请求可以返回一组对象,如:https://ebosscrm.com/api.php/job_type.json

这将很容易反序列化为List<EBossJobType>的假设T。请注意,结果中没有错误属性。

甲恶意请求到该相同的端点然而返回不同的东西: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; 
} 

我可以用这个方法来然后要么直接deserialise向右侧EBossApiResponse<T>类型(如果是真的,填充错误消息,但离开.Data财产== NULL),或deserialise右边的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; 

还是我完全找错了树,还有一个更优雅的解决这件事?

回答

9

您至少可以用JToken.Parse()代替JObject.Parse(),因为JTokenJObjectJArray的基类。然后您可以检查结果是否为JArrayJObject(或者可能是JValue,如整数)。

var result = JToken.Parse(response); 

if (result is JArray) 
{ 
    // ... 
} 
else if (result is JObject) 
{ 
    // ... 
} 

也看看documentation for JToken

+0

我想知道在地球上我怎么可能错过了阅读文档,并刚回到他们我意识到为什么:我正在使用.NET Framework v3.5进行项目集成,因此Json.Net 3.5,JToken.Parse()稍后被引入Json.Net。我没有它:( –

+0

回来进行清理。虽然它当时没有解决问题,但现在肯定是正确的答案。 –