2012-06-20 23 views
41

這裏是我的簡單User POCO類:使用JsonConvert.DeserializeObject反序列化JSON來一個C#POCO類

/// <summary> 
/// The User class represents a Coderwall User. 
/// </summary> 
public class User 
{ 
    /// <summary> 
    /// A User's username. eg: "sergiotapia, mrkibbles, matumbo" 
    /// </summary> 
    public string Username { get; set; } 

    /// <summary> 
    /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan" 
    /// </summary> 
    public string Name { get; set; } 

    /// <summary> 
    /// A User's location. eh: "Bolivia, USA, France, Italy" 
    /// </summary> 
    public string Location { get; set; } 

    public int Endorsements { get; set; } //Todo. 
    public string Team { get; set; } //Todo. 

    /// <summary> 
    /// A collection of the User's linked accounts. 
    /// </summary> 
    public List<Account> Accounts { get; set; } 

    /// <summary> 
    /// A collection of the User's awarded badges. 
    /// </summary> 
    public List<Badge> Badges { get; set; } 

} 

而且我使用反序列化JSON響應爲User對象(這實際JSON call is here方法):

private User LoadUserFromJson(string response) 
{ 
    var outObject = JsonConvert.DeserializeObject<User>(response); 
    return outObject; 
} 

這觸發一個例外:

無法反序列化當前的JSON對象(例如{「name」:「value」}) 分爲 'System.Collections.Generic.List`1 [CoderwallDotNet.Api.Models.Account]' 因爲該類型需要JSON數組(例如[1,2,3 ])正確地反序列化 。

爲了解決這個錯誤或者改變JSON來JSON數組 (例如[1,2,3]),或改變它的反序列化類型,以便它是一個正常 .NET類型(例如不是原始類型像整數,而不是像數組或列表的集合 類型),該對象可以從JSON 對象反序列化。 JsonObjectAttribute也可以添加到類型中,以強制它從一個JSON對象反序列化。路徑「accounts.github」,1號線, 位置129

從未接觸過這種DeserializeObject方法之前工作過,我有種陷在這裏。

我確定POCO類中的屬性名稱與JSON響應中的名稱相同。

我可以嘗試將JSON反序列化到此POCO類中嗎?

+0

似乎我遲到了,但看到我的答案。使用'JsonProperty'比編寫'JsonConverter'更容易(和可讀) –

+0

然後你可能會看到類似的東西。 http://stackoverflow.com/questions/25672338/dynamically-deserialize-json-into-any-object-passed-in-c-sharp – Jim

回答

69

這是一個工作示例。

關鍵點是:

  • Accounts
  • 使用JsonProperty屬性

的宣言。

using (WebClient wc = new WebClient()) 
{ 
    var json = wc.DownloadString("http://coderwall.com/mdeiters.json"); 
    var user = JsonConvert.DeserializeObject<User>(json); 
} 

-

public class User 
{ 
    /// <summary> 
    /// A User's username. eg: "sergiotapia, mrkibbles, matumbo" 
    /// </summary> 
    [JsonProperty("username")] 
    public string Username { get; set; } 

    /// <summary> 
    /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan" 
    /// </summary> 
    [JsonProperty("name")] 
    public string Name { get; set; } 

    /// <summary> 
    /// A User's location. eh: "Bolivia, USA, France, Italy" 
    /// </summary> 
    [JsonProperty("location")] 
    public string Location { get; set; } 

    [JsonProperty("endorsements")] 
    public int Endorsements { get; set; } //Todo. 

    [JsonProperty("team")] 
    public string Team { get; set; } //Todo. 

    /// <summary> 
    /// A collection of the User's linked accounts. 
    /// </summary> 
    [JsonProperty("accounts")] 
    public Account Accounts { get; set; } 

    /// <summary> 
    /// A collection of the User's awarded badges. 
    /// </summary> 
    [JsonProperty("badges")] 
    public List<Badge> Badges { get; set; } 
} 

public class Account 
{ 
    public string github; 
} 

public class Badge 
{ 
    [JsonProperty("name")] 
    public string Name; 
    [JsonProperty("description")] 
    public string Description; 
    [JsonProperty("created")] 
    public string Created; 
    [JsonProperty("badge")] 
    public string BadgeUrl; 
} 
+0

這導致了更多,更乾淨的代碼。我已經實現了一個自定義串行器,但我更喜歡這種方法,因爲它更精簡。再次感謝! –

+8

您是否忘記了帳戶列表<>,或者我錯過了什麼?在我看來,最初的問題是賬戶是一個列表,但這個解決方案的賬戶是一個賬戶對象......不是一個數組,而不是一個列表。 – huntharo

+2

@huntharo看起來像已更改的'Accounts'聲明 - 從'List '到'Account' - 是因爲示例JSON(在問題中鏈接)具有單個JSON對象 - 不是數組 - 用於「帳戶':''accounts「:{」github「:」sergiotapia「}' –

2

的帳戶屬性的定義如下:

"accounts":{"github":"sergiotapia"} 

你的POCO狀態是:

public List<Account> Accounts { get; set; } 

嘗試使用此JSON:

"accounts":[{"github":"sergiotapia"}] 

項目的數組(這是將被映射到列表)總是被括在方括號中。

編輯:賬戶波科將是這樣的:

class Account { 
    public string github { get; set; } 
} 

,也許其他屬性。

編輯2:要沒有一個陣列中使用的屬性如下:

public Account Accounts { get; set; } 

喜歡的東西我已經張貼在第一編輯樣品類。

+0

只是定義屬性不作爲一個列表。我正在編輯我的答案(Edit2) – Sascha

2
to fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the 
deserialized type so that it is a normal .NET type (e.g. not a primitive type like 
integer, not a collection type like an array or List) that can be deserialized from a 
JSON object.` 

整個消息表明可以序列化爲List對象,但輸入必須是JSON列表。 這意味着你的JSON必須包含

"accounts" : [{<AccountObjectData}, {<AccountObjectData>}...], 

哪裏AccountObject數據是JSON表示您的帳戶對象或您的徽章對象

什麼它似乎是目前得到的是

"accounts":{"github":"sergiotapia"} 

凡帳目是一個JSON對象(用花括號表示),而不是JSON對象數組(用括號表示),這就是你想要的。嘗試

"accounts" : [{"github":"sergiotapia"}] 
+0

實際的JSON存在問題。 –

+0

哎呀,現在編輯編輯:完成。對不起,沒有注意到;撇脂並不總是最佳的; P –

4

您可以創建一個JsonConverter。有關與您的問題類似的示例,請參見here

+0

**正是**我希望存在的東西。我一定會看看這個。謝謝! –

+0

沒問題,很高興我能幫上忙。 – SwDevMan81

4

另一個,和更簡化,方法來反序列化駱駝套管JSON字符串到帕 - 套管POCO對象是使用CamelCasePropertyNamesContractResolver

它是Newtonsoft.Json.Serialization命名空間的一部分。這種方法假定JSON對象和POCO之間唯一的區別在於屬性名稱的大小寫。如果屬性名拼寫不同,那麼您需要使用JsonProperty屬性來映射屬性名稱。

using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization; 

. . . 

private User LoadUserFromJson(string response) 
{ 
    JsonSerializerSettings serSettings = new JsonSerializerSettings(); 
    serSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
    User outObject = JsonConvert.DeserializeObject<User>(jsonValue, serSettings); 

    return outObject; 
} 
0

這不正是我想到的。如果你只有在運行時才知道的泛型類型,你該怎麼做?

public MyDTO toObject() { 
    try { 
    var methodInfo = MethodBase.GetCurrentMethod(); 
    if (methodInfo.DeclaringType != null) { 
     var fullName = methodInfo.DeclaringType.FullName + "." + this.dtoName; 
     Type type = Type.GetType(fullName); 
     if (type != null) { 
     var obj = JsonConvert.DeserializeObject(payload); 
     //var obj = JsonConvert.DeserializeObject<type.MemberType.GetType()>(payload); // <--- type ????? 
      ... 
     } 
    } 

    // Example for java.. Convert this to C# 
    return JSONUtil.fromJSON(payload, Class.forName(dtoName, false, getClass().getClassLoader())); 
    } catch (Exception ex) { 
    throw new ReflectInsightException(MethodBase.GetCurrentMethod().Name, ex); 
    } 
}