Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JsonConvert.DeserializeObject to deserialize Json to a C# POCO class

Here is my simple User POCO class:

/// <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; }  } 

And the method I'm using to deserialize a JSON response into a User object (this actual JSON call is here):

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

This fires an exception:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CoderwallDotNet.Api.Models.Account]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

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. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'accounts.github', line 1, position 129.

Having never worked with this DeserializeObject method before, I'm kind of stuck here.

I've made sure that the property names in the POCO class are the same as the names in the JSON response.

What can I try to deserialize JSON into this POCO class?

like image 383
Only Bolivian Here Avatar asked Jun 20 '12 18:06

Only Bolivian Here


People also ask

How do I deserialize JSON data?

A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.

Does JsonConvert DeserializeObject throw?

DeserializeObject can throw several unexpected exceptions (JsonReaderException is the one that is usually expected). These are: ArgumentException.

How does Newtonsoft JSON deserialize work?

Newtonsoft. Json uses reflection to get constructor parameters and then tries to find closest match by name of these constructor parameters to object's properties. It also checks type of property and parameters to match. If there is no match found, then default value will be passed to this parameterized constructor.


2 Answers

Here is a working example.

Keypoints are:

  • Declaration of Accounts
  • Use of JsonProperty attribute

.

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; } 
like image 96
L.B Avatar answered Sep 21 '22 00:09

L.B


Another, and more streamlined, approach to deserializing a camel-cased JSON string to a pascal-cased POCO object is to use the CamelCasePropertyNamesContractResolver.

It's part of the Newtonsoft.Json.Serialization namespace. This approach assumes that the only difference between the JSON object and the POCO lies in the casing of the property names. If the property names are spelled differently, then you'll need to resort to using JsonProperty attributes to map property names.

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;  } 
like image 36
John Iwasz Avatar answered Sep 24 '22 00:09

John Iwasz