5

I have this JSON text and I can't figure out how to parse the "items" property to fill up a list of items

{
    "response": {
        "success": 1,
        "current_time": 1445015502,
        "items": {
            "item1": {
                "property1": 1,
                "property2": "test",
                "property3": 4.3
            },
            "item2": {
                "property1": 5,
                "property2": "test2",
                "property3": 7.8
            }
        }
    }
}

Those are my classes yet :

public class Item
{
    public int property1 { get; set; }
    public string property2 { get; set; }
    public double property3 { get; set; }
}

public class Response
{
    public int success { get; set; }
    public string message { get; set; }
    public int current_time { get; set; }
    public List<Item> items { get; set; }
}

public class RootObject
{
    public Response response { get; set; }
}

Also, no, it's not a error. There is no [ nor ] in the JSON text. Also, the number of items in the JSON is undefined.

6
  • @EdCottrell - there is nothing wrong with JSON in questions... Pain to parse, but perfectly valid. Commented Oct 16, 2015 at 17:58
  • And I need help for the pain part, how to parse those items ? Commented Oct 16, 2015 at 18:01
  • @AlexeiLevenkov I deleted my comment before you replied. I was reading this on a mobile device and misread it. You're correct. Commented Oct 16, 2015 at 18:02
  • Are you in control of the JSON being generated? The Item#1 and Item#2 is going to be annoying to parse. Commented Oct 16, 2015 at 18:05
  • No, I don't control this, but this was just a exemple, so, yeah, the '#' char shouldn't be here. Commented Oct 16, 2015 at 18:22

2 Answers 2

3

This is easy to accomplish thanks to Json.NET and dynamic:

private RootObject Parse(string jsonString)
{
   dynamic jsonObject = JsonConvert.DeserializeObject(jsonString);
   RootObject parsed = new RootObject()
   {
        response = new Response()
        {
              success = jsonObject.response.success,
              current_time = jsonObject.response.current_time,
              message = jsonObject.response.message,
              items = ParseItems(jsonObject.response.items)
        }  
   };
   return parsed;
}

private List<Item> ParseItems(dynamic items)
{
     List<Item> itemList = new List<Item>();
     foreach (var item in items)
     {
         itemList.Add(new Item()
         {
              property1 = item.Value.property1,
              property2 = item.Value.property2,
              property3 = item.Value.property3
         });
     }
     return itemList;
}
Sign up to request clarification or add additional context in comments.

5 Comments

No problem! I tested it with you sample JSON and it worked like a charm. If you encounter any problems, tell me!
Okay, this is fine, but, now, let's add another difficulty, what if the object name aren't "item1", "item2", "item3" ... anymore but complety random name, we can't find the name in advence. Is it still possible ?
@Arkarr Yes, see my edit (Updated my ParseItems method).
Woah, it was that simple and I couldn't see it. Thanks !
@Arkarr Always glad to help! If you feel that this answer solves your problem, please proceed to mark it as the accepted answer
0

items isn't an array int he JSON, it's an object:

"items": {
    "item1": {
        "property1": 1,
        "property2": "test",
        "property3": 4.3
    },
    "item2": {
        "property1": 5,
        "property2": "test2",
        "property3": 7.8
    }
}

So it won't deserialize into a collection:

public List<Item> items { get; set; }

Instead, create a type for it:

public class Items
{
    public Item item1 { get; set; }
    public Item item2 { get; set; }
}

And use that in the parent object:

public class Response
{
    public int success { get; set; }
    public string message { get; set; }
    public int current_time { get; set; }
    public Items items { get; set; }
}

4 Comments

Okay, well, the '#' wasn't that smart from my part, it was just for the exemple. Also, this solution is not cool, since I don't want to write download ALL the items. And, if I decide to edit the name of 1 of the the items, your solutions won't work. Damn.. I'm stuck. Also, the number of tiems can change at any time, and I don't want to hardcode them.
@Arkarr: What do you mean by "download all the items"? Are you somehow buffering the JSON response? That's going to make de-serialization a lot harder, since you'd only be de-serializing part of an otherwise incomplete JSON string. And, yes, if you edit property names in the JSON, you'd need to edit the property names in the consuming code. That's pretty much true anywhere. So it's really not clear what the problem is or what you're trying to do.
Well, I download the JSON string from a website, wich shouldn't create any problem, since it's a string returned, just like in my exemples (but with a lot more items.). Also, I didn't mean "download" but "down" (corrected now, miss type).
@Arkarr: You could deserialize it into a dynamic, though consuming code which references the properties of those objects is still going to have to explicitly reference them so you don't really gain much in exchange for deferring potential deserialization errors to a less opportune time. But if you want to have a static type which matches the JSON structure, then you need to create a static type which matches the JSON structure. (Note that it can match any subset of that structure, only the parts you need. You don't have to create C# properties that you won't use.)