1

I'm fairly new to json, and I'm trying to convert some json content to a C# class to store it for later use. I'm having a problem trying to create a class which is suitable for the data structure. An example of the json content is shown below.

Json Data

{
    "FirstItem": {
        "id": 1,
        "type": "foo",
        "colours": ["blue", "black", "green"],
        "reviews": {
            "positive": ["The best", "unbelievable", "Awesome"],
            "negative": ["Sh*t", "Awful", "Dire", "Terrible", "Appalling"],
            "neutral": ["OK", "Meh"]
        }
    },
    "SecondItem": {
        "id": 2,
        "type": "bar",
        "colours": ["red", "white", "yellow"],
        "reviews": {
            "positive": ["Great", "Amazing", "Fantastic", "Perfect", "Uplifting"],
            "negative": ["Terrible", "Shocking", "abysmal"],
            "neutral": ["OK", "Standard", "Vanilla"]
        }
    }
}

Edit:

It's worth noting that this is just a small sample of the json data, and I expect to be working with a much larger data set which is always in this format, however the FirstItem, SecondItem (names?) will always be different. I could potentially end up with a MillionthItem.

C# Class

I have created a class based on my limited understanding of the json data above. I think this is where the problem lies - I dont think this class is suitable based on the json above. Here's what I have.

public class Data
{
    public string name {get; set;}
    public int id {get; set;}
    public string type {get; set;}
    public string[] colours {get; set;}
    public Reviews reviews {get; set;}
}

public class Reviews
{
    public string[] positive {get; set;}
    public string[] negative {get; set;}
    public string[] neutral {get; set;}
}

Converting json to class

To try and convert this, I am using JsonConvert to deserialize the data to a List of a class which I have created. For example:

var client = new RestClient(url);
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);

var result = JsonConvert.DeserializeObject<List<Data>>(response.Content);

Exception

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[namespace.class]' 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.

Summary

I'd appreciate some advice on understanding the json format above, and how I can successfuly convert this

Solution

dbc suggested storing this information in a dictionary, which was exactly what I was needing to do - this allows me to capture the name (FirstItem, SecondItem etc.) as the key and the rest of the class Data as the value.

var result = JsonConvert.DeserializeObject<Dictionary<string, Data>>(response.Content);
Community
  • 1
  • 1
devklick
  • 2,000
  • 3
  • 30
  • 47
  • Have you tried using a Json to poco converter? There's a few online ones that sometimes do a good job. – Chris Nevill Mar 18 '18 at 16:26
  • Are `"FirstItem"`, `"SecondItem"` and so on variable and not fixed? If so then use a dictionary: `var result = JsonConvert.DeserializeObject>(response.Content);` – dbc Mar 18 '18 at 16:34
  • See for instance [How can I parse a JSON string that would cause illegal C# identifiers?](https://stackoverflow.com/a/24536564/3744182) or [Create a strongly typed c# object from json object with ID as the name](https://stackoverflow.com/a/34213724/3744182) for pre-existing questions. – dbc Mar 18 '18 at 16:40
  • @dbc, this is exactly what I was needing. This allows me to capture the 'name' (FirstItem etc.) and the data for each record that is returned from the API call. Thanks muchly! – devklick Mar 18 '18 at 16:45

1 Answers1

7

Just copy your json and do Edit->Paste Special->Paste Json As Classes in Visual Studio - it will create you the matching class structure.

    public class Rootobject
    {
        public Firstitem FirstItem { get; set; }
        public Seconditem SecondItem { get; set; }
    }

    public class Firstitem
    {
        public int id { get; set; }
        public string type { get; set; }
        public string[] colours { get; set; }
        public Reviews reviews { get; set; }
    }

    public class Reviews
    {
        public string[] positive { get; set; }
        public string[] negative { get; set; }
        public string[] neutral { get; set; }
    }

    public class Seconditem
    {
        public int id { get; set; }
        public string type { get; set; }
        public string[] colours { get; set; }
        public Reviews1 reviews { get; set; }
    }

    public class Reviews1
    {
        public string[] positive { get; set; }
        public string[] negative { get; set; }
        public string[] neutral { get; set; }
    }

Then usage will be like:

        var rootObject = JsonConvert.DeserializeObject<Rootobject>(jsonString);
Vidmantas Blazevicius
  • 4,652
  • 2
  • 11
  • 30
  • I never knew this existed, thanks for pointing this out! The probelm with using this is that a class would have to exist for every item, and I expect much more than just `FirstItem` & `SecondItem`. I've updated my post to reflect this. – devklick Mar 18 '18 at 16:39
  • 1
    It's no problem, but your Json structure is incorrect then - you are really looking for array of Items, so your json should start with `[` and end with `]`. If you can change the structure then you could add `JsonArray` attribute to `FirstItem` class and deserialize directly into a `List` (should probably rename the class then as well to `Item`) – Vidmantas Blazevicius Mar 18 '18 at 16:43