2015-05-04 22 views
26

我玩的收穫API和我試圖自動實體映射儘可能地簡單,不幸的是當我做了要求如GET /projects它產生的結果,像這樣:動態反序列化到一個屬性RestSharp

因爲它要尋找一個叫 Project財產

client.Execute<List<Project>>(request) 

[{ 
    project: { 
     name: "Test" 
    } 
}, 
{ 
    project: { 
     name: "Test 2" 
}] 

在RestSharp,我不能直接做到這一點。所以,我不得不做出這樣的具有財產另一個類,並調用它像這樣:

client.Execute<List<ProjectContainer>>(request) 

我不想讓每一個實體「容器」類,所以我想我找到了一個巧妙的解決使一類我可以在所有使用:

public class ListContainer<T> where T : IHarvestEntity 
{ 
    public T Item { get; set; } 
} 

但是,當然,解串器不知道它需要實體名稱(或「項目」)映射到財產Item。在restsharp文檔中,我發現我可以使用[DeserializeAs(Name = "CustomProperty")]來告訴解串器將哪個字段映射到此屬性。然而,屬性只允許常量,這意味着我不能這樣做:

[DeserializeAs(Name = typeof(T).FullName)] 
public T Item { get; set; } 

有沒有人知道一個聰明的解決方案呢?所以我不必創建10個不同的容器類?

回答

6

我建議你使用Json的XPath等價物。用Json.NET你可以parse這個字符串並創建一個動態對象。

With SelectToken您可以查詢值,或使用Linq

的代碼看起來是這樣的(我沒有測試):

// execute the request 
RestResponse response = client.Execute(request); 
var content = response.Content; // raw content as string 

JObject o = JObject.Parse(content); 

IList<string> projectNames = o.SelectToken("project").Select(s => (string)s.name).ToList(); 

您可以編碼路徑或反正你喜歡的配置路徑。

---編輯---

下面是我測試過,JSON字符串轉換爲一個項目列表的例子。

var projects = JArray.Parse(response.Content).Select(r => new Project(r["project"]["name"].Value<string>())).ToList(); 
+0

動態對象可能是問題的答案,但很多開發商會警告你只實現XYZModel類並使用它們;您可以獲得編譯器的所有好處和保證,並且不會冒險(同一類)運行時異常。 –

+1

民主我想我應該給你賞金,但我覺得從Mikko的答案更正確地回答了我的情況這個問題。因爲在你的例子中,我失去了自動映射到實體,這是背後的全部想法。我錯了嗎? – Chris

+0

使用Mikko答案中的項目對象可以映射到對象:var project = new Project(o.SelectToken(「project」)。SelectToken(「name」)。Value) –

2

爲了保持它很簡單,你可以使用List<dynamic>和訪問屬性/名字與一個班輪性質。

var names = client.Execute<List<dynamic>>(request).Data.Select(
       item => item["project"]["name"]).ToList(); // list of names 

如果這還不夠,那麼你可以即興發揮自己的映射並提取例如集合Project實例:

var projects = client.Execute<List<dynamic>>(request).Data.Select(
       item => Map<Project>(item)).ToList(); // list of Project instances 

其中Map方法可以像

public T Map<T>(dynamic item) where T : class 
{ 
    // inline for clarity 
    var mappings = new Dictionary<Type,Func<dynamic,object>> 
     { 
      { typeof(Project), map => new Project(map["project"]["name"]) } 
     }; 

    return (T)mappings[typeof(T)].Invoke(item); 
} 
給出 Project

被定義爲

public class Project 
{ 
    public Project(string name) 
    { 
     Name = name; 
    } 
    public string Name { get; set; } 
}