Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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"
    ]
}
share|improve this question

5 Answers

Use JsonConvert.DeserializeObject(string json);

Create your classes on http://json2csharp.com

share|improve this answer
2  
Ok, that link is fantastic! – Dirk Bester Jul 18 '12 at 17:50
Superb, thanks! +1 – Lee Taylor Aug 31 '12 at 16:43
Saved my day! +1 – BaBu Oct 5 '12 at 12:13
This is awesome. Thanks! – Bizorke Jan 7 at 22:18
1  
Seriously! What a lifesaver! – pierceboggan Feb 9 at 0:25
show 1 more comment

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

share|improve this answer
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? – user305145 Mar 30 '10 at 15:18
updated answer... – Dave Swersky Mar 30 '10 at 16:14
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?? – Hamish Grubijan Apr 20 '12 at 0:48

You can use:

JsonConvert.Populate(json,obj);

here: json is the json string,obj is the target object

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

share|improve this answer
1  
it's PopulateObject - Populate is not in the object model. – amok Mar 16 '12 at 20:36

Assuming your sample data is correct, your givenname, and other entries wrapped in brackets are arrays in JS... you'll want to use List for those data types. and List for say accountstatusexpmaxdate... I think you example has the dates incorrectly formatted though, so uncertain as to what else is incorrect in your example.

This is an old post, but wanted to make note of the issues.

share|improve this answer

You can try checking some of the class generators online for further information, however i belive some of the answers have been useful here's my approach that maybe could be useful.

The following code was made with a dynamic method in mind.

dynObj = (JArray)JsonConvert.DeserializeObject(nvm);

        foreach (JObject item in dynObj)
        {
            foreach (JObject trend in item["trends"])
            {
         Console.WriteLine({0}-{1}-{2}",trend["query"],trend["name"],trend["url"]);

            }
        }

This code basically allows you to access members contained in the Json string. Jus a different way without the need of the classes. Query, trend and url are the objects contained in the Json string.

You can also use this link http://json2csharp.com/. Don't trust the classes a 100% but you get the idea.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.