2012-10-30 57 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

回來進行清理。雖然它當時沒有解決問題,但現在肯定是正確的答案。 –