-2

I have a JSON class like this

{
    "Items": {
        "Item_1A": {
            "prop1": "string",
            "prop2": "string",
            "prop3": 1,
            "prop4": [{
                "prop_x": 100
            },
            {
                "prop_y": 200
            }]
        },
        "Item2B": {
            "prop1": "string",
            "prop2": "string",
            "prop3": 14,
            "prop4": [{
                "prop_z": 300
            }]
        }
    }
}

How could I make it into C# classes? Here is what I have so far:

public class Info
{
    public string prop1 {get;set;}
    public string prop2 {get;set;}
    public int prop3 {get;set;}
    public Dictionary<string, List<int>> prop4 {get;set;}
}
public class Response
{
    public Dictionary<string, List<Info>> Item {get;set;}
}

I tried to follow this link, but did not work Deserialize nested JSON into C# objects

dbc
  • 104,963
  • 20
  • 228
  • 340
maxrena
  • 33
  • 1
  • 6
  • 1
    What have you tried already? What _specifically_ is not working? – maccettura Sep 12 '18 at 20:48
  • 1
    I'm not sure that this is valid JSON, "int" should be in quotes. – Ron Beyer Sep 12 '18 at 20:49
  • I found the link, and I followed to use Dictionnary> but it returned just null. – maxrena Sep 12 '18 at 20:53
  • 1
    I think the JSON is malformed. There shouldn't be a comma after the square bracket after `"prop_y": int` – ctoph Sep 12 '18 at 20:55
  • my bad, I just edited – maxrena Sep 12 '18 at 21:01
  • After a few debugs, I found out the reason for that, but now I got into another one: Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1 – maxrena Sep 12 '18 at 21:31
  • I'm pretty sure your json is still malformed. For an easy method check out QuickType, pretty much generates everything for you. https://app.quicktype.io/ – DCCoder Sep 12 '18 at 21:31
  • the JSON file is ok, mb I just don't know how to type it correctly here. But now I got into trouble when deserializing it, please help with the new error. – maxrena Sep 12 '18 at 21:34
  • See my answer... – Kit Sep 12 '18 at 22:14
  • Please confirm what serializer you are using. Most likely it's [tag:json.net] but it might be something else like [tag:javascriptserializer] or [tag:datacontractjsonserializer]. – dbc Sep 13 '18 at 01:05
  • Try http://json2csharp.com/ – Erik J. Sep 22 '18 at 00:14

4 Answers4

0

Here's a tip to create proxy classes after a json:

First of all, to make sure it is a valid JSON, go to this website and run the validator: https://jsonlint.com/

If it is ok, there are some tools that convert json and xml to a c# proxy class directly like: http://json2csharp.com/ : https://xmltocsharp.azurewebsites.net/

Now there you go! just copy them to your Model and start using it.

  • I know about the converter, but my JSON file can go up to thousands of data. The question is like a sample for 2 keys, what if I have 20000 keys? How could that converter do? The reason I asked for that because there was a similar question in the link I posted with above, and the solution was the Dictionary<>, but when I used with mine, I just can't make it work. – maxrena Sep 12 '18 at 21:41
  • They are different keys values, you know? Or you never read all the info I gave above before comments? How about checking the link I posted with my question? – maxrena Sep 12 '18 at 22:09
0

Just some small changes to your model. Your prop4 is instead a List or Array.

public class Info
{
  public string prop1 {get;set;}
  public string prop2 {get;set;}
  public int prop3 {get;set;}
  public List<Dictionary<string, List<int>>> prop4 {get;set}
}
public class  Response
{
  public class Dictionary<string, Info> Items {get;set;} // Should be named Items
}
Yves Israel
  • 408
  • 3
  • 5
  • https://github.com/dotabuff/d2vpkr/blob/master/dota/scripts/npc/items.json may I ask you with this json file for example, am I doing it right with making class? Or what did I do wrong? – maxrena Sep 12 '18 at 22:37
0

Your prop4 is a Dictionary<string, List<int>>, which when serialized looks something like this (I've omitted $type properties in the emitted JSON for brevity):

{
   "X": {
      "$values": [ 1, 2 ]
   },
   "Y": {
      "$values": [ 3, 4 ]
   }    
}

Your JSON, while well formed, is "shaped" wrong. It looks more like an array containing a dictionary of one item.

In the JSON above, X and Y are keys in the dictionary, which is a "regular object" modeled in JSON. The $values represents the list of integers for each key.

Kit
  • 20,354
  • 4
  • 60
  • 103
0

Your data model should be as follows:

public class Info
{
    public string prop1 {get;set;}
    public string prop2 {get;set;}
    public int prop3 {get;set;}
    // Modified from 
    //public Dictionary<string, List<int>> prop4 {get;set}
    public List<Dictionary<string, int>> prop4 {get;set;}
}

public class Response
{
    // Modified from 
    //public class Dictionary<string, List<Info>> Item {get;set;}
    public Dictionary<string, Info> Items {get;set;}
}

Notes:

  • Response.Item should have been named Items.

  • In your JSON, "Items" is an object with variably-named object-valued properties:

    {
        "Items": {
            "Item_1A": { },
            "Item2B": { }
        }
    }
    

    This should be modeled as a Dictionary<string, T> for an appropriate non-collection type T. Assuming you are using see Serialization Guide: Dictionaries for details. If not, behaves similarly.

    Your data model, public class Dictionary<string, List<Info>> Items, would have been appropriate for an object with variably-named array-valued properties:

    {
        "Items": {
            "Item_1A": [{ },{ }],
            "Item2B": [{ }]
        }
    }
    

    But this is not what you have.

  • Meanwhile "prop4" is an array containing object with variably-named object-valued properties such as:

    "prop4": [ // Outer container is an array
      {        // Inner container is an object
        "prop_x": 100
      },
      {
        "prop_y": 200
      }
    ]
    

    Thus a collection such as List<T> should be used as the outer generic type:

    public List<Dictionary<string, int>> prop4 {get;set;}
    

    See Serialization Guide: IEnumerable, Lists, and Arrays.

  • As you have noticed, code-generation tools such as those mentioned in How to auto-generate a C# class file from a JSON object string generally cannot recognize JSON objects with variable property names. In such a situation an auto-generated class may need to get manually replaced with an appropriate Dictionary<string, T> property in the containing type.

Sample working fiddle here.

dbc
  • 104,963
  • 20
  • 228
  • 340