Hard to describe in words, but the API call I'm using returns JSON strings with integer names rather than something that can easily be converted to a class. You'll see in the example what I mean.
To start, I've examined the following Stackoverflow posts already, and they're helping but not giving me a complete solution to this particular JSON to C# class deserialization issue I'm having:
- Parsing JSON to C# Object....
- How to Deserialize Objects Containing Arrays....
- Create a Strongly Typed C# Object....
- C# JSON.NET Invalid Type
Nuts and bolts and why are the posts above not exactly helping?
Here's the JSON:
{
"related_objects": {
"user": {
"4243432": {
"id": 4243432,
"name": "Mary Poppins",
"email": "mary@poppins.com",
"has_pic": false,
"pic_hash": null,
"active_flag": false
},
"10658120": {
"id": 10658120,
"name": "Jack Spratt",
"email": "jack@couldeatnofat.com",
"has_pic": false,
"pic_hash": null,
"active_flag": true
}
},
"person": {
"425": {
"id": 425,
"name": "Jack L. Spratt",
"email": [{
"label": "work",
"value": "jack@couldeatnofat.com",
"primary": true
}
],
"phone": [{
"label": "work",
"value": "7045551212",
"primary": true
}
]
}
},
"organization": {
"96": {
"id": 96,
"name": "Leopards Domain",
"people_count": 1,
"owner_id": 4243432,
"address": null,
"cc_email": "spottedcat@kittens.com"
},
"220": {
"id": 220,
"name": "Gentle Giants",
"people_count": 0,
"owner_id": 10658120,
"address": null,
"cc_email": "wolf@hound.com"
},
"221": {
"id": 221,
"name": "Mice, Inc",
"people_count": 0,
"owner_id": 10658120,
"address": null,
"cc_email": "marvin@rodentsrus.com"
},
"222": {
"id": 222,
"name": "Footware",
"people_count": 0,
"owner_id": 10658120,
"address": null,
"cc_email": "jenny@socksandshoes.com"
},
"223": {
"id": 223,
"name": "Ignore Univ",
"people_count": 1,
"owner_id": 10658120,
"address": null,
"cc_email": "talktothehand@ignoreu.com"
}
}
}
}
If I run this through my favorite JSON to C# converter site, I'll get something like this:
public class __invalid_type__4243432
{
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
public bool has_pic { get; set; }
public object pic_hash { get; set; }
public bool active_flag { get; set; }
}
Which, I would be tempted to use, if it weren't for the fact that this call is getting something for a specific user id. If I ask for the same information for another user id, I'll get different integer returns for the name attributes.
What have I done? Well, I've read the postings noted, and I'm able to do this:
public class UserProperties
{
public int id { get; set; }
public string name { get; set; }
public string email { get; set; }
public string has_pic { get; set; }
public string pic_hash { get; set; }
public string active_flag { get; set; }
}
And, as a test, use this constant string:
public const string USERENTRIES =
"{ " +
" \"4243432\": { " +
" \"id\": 4243432, " +
" \"name\": \"Mary Poppins\", " +
" \"email\": \"mary@poppins.com\", " +
" \"has_pic\": false, " +
" \"pic_hash\": null, " +
" \"active_flag\": false " +
" }, " +
" \"10658120\": { " +
" \"id\": 10658120, " +
" \"name\": \"O. Susanna\", " +
" \"email\": \"O@susanna.com\", " +
" \"has_pic\": false, " +
" \"pic_hash\": null, " +
" \"active_flag\": true " +
" } " +
"}";
And convert it like this, successfully:
Dictionary<string, UserProperties> userentries = JsonConvert.DeserializeObject<Dictionary<string, UserProperties>>(USERENTRIES);
You're probably wondering what the problem is. well, it's the fact that this dictionary construct is actually the value for the name "user" in the user/value JSON pair, as noted:
"user": {
"4243432": {
"id": 4243432,
"name": "Mary Poppins",
"email": "mary@poppins.com",
"has_pic": false,
"pic_hash": null,
"active_flag": false
},
"10658120": {
"id": 10658120,
"name": "Jack Spratt",
"email": "jack@couldeatnofat.com",
"has_pic": false,
"pic_hash": null,
"active_flag": true
}
}
What I need, in C#, I think, is something like this:
[JsonObject(Description = "user")]
public class User
{
public Dictionary<string, UserProperties> UserProperties { get; set; }
}
Which I would used to make the conversion like so:
var user = JsonConvert.DeserializeObject<User>(USER);
This returns null.
This is my test JSON constant:
public const string USER =
" { " +
" \"user\": { " +
" \"4243432\": { " +
" \"id\": 4243432, " +
" \"name\": \"Mary Poppins\", " +
" \"email\": \"mary@poppins.com\", " +
" \"has_pic\": false, " +
" \"pic_hash\": null, " +
" \"active_flag\": false " +
" }, " +
" \"10658120\": { " +
" \"id\": 10658120, " +
" \"name\": \"O. Susanna\", " +
" \"email\": \"O@Susanna.com\", " +
" \"has_pic\": false, " +
" \"pic_hash\": null, " +
" \"active_flag\": true " +
" } " +
" } " +
" }";
I've tried to provide everything here if anyone wants to try it out. Of course, I'm using Newtonsoft.
I feel like I'm missing just one thing. The difference between this scenario and the others in the other postings is that the odd name/value pairs are contained within another name. In the examples, the odd name/value pairs were either not contained within anything or were themselves containers of something else.
Seems to me that the deserialization of the odd name/value pair needs to be done in some way that is apart from the deserialization of the parent class.
If this needs a specific converter built, then I'd appreciate pointers to how to do that. Likewise, if an attribute set makes it easier, that too. I noted that in one posting, the responder suggesting specifying attributes. I'd appreciate any examples of using attributes to resolve this also.