Deserializing JSON data to C# using JSON.NET

374,514

Solution 1

Use

var rootObject =  JsonConvert.DeserializeObject<RootObject>(string json);

Create your classes on JSON 2 C#


Json.NET documentation: Serializing and Deserializing JSON with Json.NET

Solution 2

Have you tried using the generic DeserializeObject method?

JsonConvert.DeserializeObject<MyAccount>(myjsondata);

Any missing fields in the JSON data should simply be left NULL.

UPDATE:

If the JSON string is an array, try this:

var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata);

jarray should then be a List<MyAccount>.

ANOTHER UPDATE:

The exception you're getting isn't consistent with an array of objects- I think the serializer is having problems with your Dictionary-typed accountstatusmodifiedby property.

Try excluding the accountstatusmodifiedby property from the serialization and see if that helps. If it does, you may need to represent that property differently.

Documentation: Serializing and Deserializing JSON with Json.NET

Solution 3

You can use:

JsonConvert.PopulateObject(json, obj);

here: json is the json string,obj is the target object. See: example

Note: PopulateObject() will not erase obj's list data, after Populate(), obj's list member will contains its original data and data from json string

Solution 4

Building off of bbant's answer, this is my complete solution for deserializing JSON from a remote URL.

using Newtonsoft.Json;
using System.Net.Http;

namespace Base
{
    public class ApiConsumer<T>
    {
        public T data;
        private string url;

        public CalendarApiConsumer(string url)
        {
            this.url = url;
            this.data = getItems();
        }

        private T getItems()
        {
            T result = default(T);
            HttpClient client = new HttpClient();

            // This allows for debugging possible JSON issues
            var settings = new JsonSerializerSettings
            {
                Error = (sender, args) =>
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
            };

            using (HttpResponseMessage response = client.GetAsync(this.url).Result)
            {
                if (response.IsSuccessStatusCode)
                {
                    result = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result, settings);
                }
            }
            return result;
        }
    }
}

Usage would be like:

ApiConsumer<FeedResult> feed = new ApiConsumer<FeedResult>("http://example.info/feeds/feeds.aspx?alt=json-in-script");

Where FeedResult is the class generated using the Xamasoft JSON Class Generator

Here is a screenshot of the settings I used, allowing for weird property names which the web version could not account for.

Xamasoft JSON Class Generator

Solution 5

I found my I had built my object incorrectly. I used http://json2csharp.com/ to generate me my object class from the JSON. Once I had the correct Oject I was able to cast without issue. Norbit, Noob mistake. Thought I'd add it in case you have the same issue.

Share:
374,514

Related videos on Youtube

Govind Malviya
Author by

Govind Malviya

MS stack (.NET,C#,ASP.NET (Webform and MVC),Web API,SQL server) NoSQL (MongoDB) NodeJs And I am working at LoginRadius Occasionally I write blogs and work on Open Source projects

Updated on January 04, 2020

Comments

  • Govind Malviya
    Govind Malviya over 4 years

    I'm relatively new to working with C# and JSON data and am seeking guidance. I'm using C# 3.0, with .NET3.5SP1, and JSON.NET 3.5r6.

    I have a defined C# class that I need to populate from a JSON structure. However, not every JSON structure for an entry that is retrieved from the web service contains all possible attributes that are defined within the C# class.

    I've been being doing what seems to be the wrong, hard way and just picking out each value one by one from the JObject and transforming the string into the desired class property.

    JsonSerializer serializer = new JsonSerializer();
    var o = (JObject)serializer.Deserialize(myjsondata);
    
    MyAccount.EmployeeID = (string)o["employeeid"][0];
    

    What is the best way to deserialize a JSON structure into the C# class and handling possible missing data from the JSON source?

    My class is defined as:

      public class MyAccount
      {
    
        [JsonProperty(PropertyName = "username")]
        public string UserID { get; set; }
    
        [JsonProperty(PropertyName = "givenname")]
        public string GivenName { get; set; }
    
        [JsonProperty(PropertyName = "sn")]
        public string Surname { get; set; }
    
        [JsonProperty(PropertyName = "passwordexpired")]
        public DateTime PasswordExpire { get; set; }
    
        [JsonProperty(PropertyName = "primaryaffiliation")]
        public string PrimaryAffiliation { get; set; }
    
        [JsonProperty(PropertyName = "affiliation")]
        public string[] Affiliation { get; set; }
    
        [JsonProperty(PropertyName = "affiliationstatus")]
        public string AffiliationStatus { get; set; }
    
        [JsonProperty(PropertyName = "affiliationmodifytimestamp")]
        public DateTime AffiliationLastModified { get; set; }
    
        [JsonProperty(PropertyName = "employeeid")]
        public string EmployeeID { get; set; }
    
        [JsonProperty(PropertyName = "accountstatus")]
        public string AccountStatus { get; set; }
    
        [JsonProperty(PropertyName = "accountstatusexpiration")]
        public DateTime AccountStatusExpiration { get; set; }
    
        [JsonProperty(PropertyName = "accountstatusexpmaxdate")]
        public DateTime AccountStatusExpirationMaxDate { get; set; }
    
        [JsonProperty(PropertyName = "accountstatusmodifytimestamp")]
        public DateTime AccountStatusModified { get; set; }
    
        [JsonProperty(PropertyName = "accountstatusexpnotice")]
        public string AccountStatusExpNotice { get; set; }
    
        [JsonProperty(PropertyName = "accountstatusmodifiedby")]
        public Dictionary<DateTime, string> AccountStatusModifiedBy { get; set; }
    
        [JsonProperty(PropertyName = "entrycreatedate")]
        public DateTime EntryCreatedate { get; set; }
    
        [JsonProperty(PropertyName = "entrydeactivationdate")]
        public DateTime EntryDeactivationDate { get; set; }
    
      }
    

    And a sample of the JSON to parse is:

    {
        "givenname": [
            "Robert"
        ],
        "passwordexpired": "20091031041550Z",
        "accountstatus": [
            "active"
        ],
        "accountstatusexpiration": [
            "20100612000000Z"
        ],
        "accountstatusexpmaxdate": [
            "20110410000000Z"
        ],
        "accountstatusmodifiedby": {
            "20100214173242Z": "tdecker",
            "20100304003242Z": "jsmith",
            "20100324103242Z": "jsmith",
            "20100325000005Z": "rjones",
            "20100326210634Z": "jsmith",
            "20100326211130Z": "jsmith"
        },
        "accountstatusmodifytimestamp": [
            "20100312001213Z"
        ],
        "affiliation": [
            "Employee",
            "Contractor",
            "Staff"
        ],
        "affiliationmodifytimestamp": [
            "20100312001213Z"
        ],
        "affiliationstatus": [
            "detached"
        ],
        "entrycreatedate": [
            "20000922072747Z"
        ],
        "username": [
            "rjohnson"
        ],
        "primaryaffiliation": [
            "Staff"
        ],
        "employeeid": [
            "999777666"
        ],
        "sn": [
            "Johnson"
        ]
    }
    
  • Admin
    Admin about 14 years
    Thanks. However I get an error of "Cannot deserialize JSON array into type 'System.String'." when it's trying to deserialize (for example) the JSON givenname array into the class GivenName string. The JSON attributes that I have defined as string in the C# class are only ever single element arrays. This is why I started picking out the values one by one as I ran in to this kind of issue during the deserialize process. Other magic that I am overlooking?
  • amok
    amok about 12 years
    it's PopulateObject - Populate is not in the object model.
  • Hamish Grubijan
    Hamish Grubijan about 12 years
    So ... DateTime AccountStatusExpiration (for instance) is not nullable as defined in the code. What would it take to make it nullable? Simply change DateTime to DateTime??
  • Jonathan Allen
    Jonathan Allen almost 9 years
    Visual Studio also has a Paste JSON as Classes option in the Edit-Paste Special menu.
  • jward01
    jward01 over 7 years
    This worked PERFECT for me! I was having issues where I had a pretty complex JSON string, when I tried to cast it to C# objects, anything marked as 'NotNull' would be missing from the object, even though it was present in the JSON string to begin with. Very strange. I used this method and it worked PERFECT!