0

I have the following JSON:

[{
    "theme-my-login": 
    {
        "latest_version":"6.4.7",
        "last_updated":"2017-01-06T18:14:00.000Z",
        "popular":true,
        "vulnerabilities":
        [
            {
                "id":6043,
                "title":"Theme My Login 6.3.9 - Local File Inclusion",
                "created_at":"2014-08-01T10:58:35.000Z",
                "updated_at":"2015-05-15T13:47:24.000Z",
                "published_date":null,
                "references":
                {
                    "url":["http://packetstormsecurity.com/files/127302/","http://seclists.org/fulldisclosure/2014/Jun/172","http://www.securityfocus.com/bid/68254/","https://security.dxw.com/advisories/lfi-in-theme-my-login/"]
                },
                "vuln_type":"LFI",
                "fixed_in":"6.3.10"
            }
        ]
    }
},{
    "other-item": 
    {
        "latest_version":"6.4.7",
        "last_updated":"2017-01-06T18:14:00.000Z",
        "popular":true,
        "vulnerabilities":
        [
            {
                "id":6043,
                "title":"Theme My Login 6.3.9 - Local File Inclusion",
                "created_at":"2014-08-01T10:58:35.000Z",
                "updated_at":"2015-05-15T13:47:24.000Z",
                "published_date":null,
                "references":
                {
                    "url":["http://packetstormsecurity.com/files/127302/","http://seclists.org/fulldisclosure/2014/Jun/172","http://www.securityfocus.com/bid/68254/","https://security.dxw.com/advisories/lfi-in-theme-my-login/"]
                },
                "vuln_type":"LFI",
                "fixed_in":"6.3.10"
            }
        ]
    }
}]

json2csharp says the object model should look like this, but that's clearly not correct

public class References
{
    public List<string> url { get; set; }
}

public class Vulnerability
{
    public int id { get; set; }
    public string title { get; set; }
    public DateTime created_at { get; set; }
    public DateTime updated_at { get; set; }
    public object published_date { get; set; }
    public References references { get; set; }
    public string vuln_type { get; set; }
    public string fixed_in { get; set; }
}

public class ThemeMyLogin
{
    public string latest_version { get; set; }
    public DateTime last_updated { get; set; }
    public bool popular { get; set; }
    public List<Vulnerability> vulnerabilities { get; set; }
}

public class RootObject
{
    public ThemeMyLogin __invalid_name__theme-my-login { get; set; }
}

that I am trying to deserialise into c# classes using Json.NET, but as the top level item doesn't have a traditional name:value pair (the name effectively is "theme-my-login" and the value is the object), it's not deserialising. Any pointers on how I can get this to deserialise? Do I need to use a custom deserialiser?

The reason I cannot use a dictionary as suggested in How can I parse a JSON string that would cause illegal C# identifiers? is that I need the value "theme-my-login" as one of the values in my model as it defines the object. I have added a second item into the json as this will be a list of items. I previously only included one to show the item structure.

Simon Holman
  • 150
  • 6
  • Use `public Dictionary LoginThemes { get; set; }` as shown in [How can I parse a JSON string that would cause illegal C# identifiers?](https://stackoverflow.com/q/24536533/3744182). – dbc Feb 14 '18 at 03:09
  • I have amended the question to explain a few further points why the proposed solution will not work. – Simon Holman Feb 14 '18 at 06:51
  • I think this is actually a duplicate then: [Deserializing a list of objects with different names in JSON.NET](https://stackoverflow.com/q/46355071/3744182). That answer says to deserialize to a `List>` – dbc Feb 14 '18 at 07:10

1 Answers1

0

You need to deserialize to List<Dictionary<string, ThemeMyLogin>> like so:

var root = JsonConvert.DeserializeObject<List<Dictionary<string, ThemeMyLogin>>>(json);

The code-generation site http://json2csharp.com/ has some limitations of which you need to be aware:

  1. The JSON standard allows for two types of container:

    • The array, which is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).

    • The object, which is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace).


    If your root container is an array, http://json2csharp.com/ will auto-generate a RootObject model to deserialize each object in the array. To actually deserialize the entire array you need to deserialize to a collection of root objects such as a List<RootObject>. See Serialization Guide: IEnumerable, Lists, and Arrays.

  2. When a JSON property corresponds to an invalid c# identifier, http://json2csharp.com/ will "helpfully" add a property to the containing type that looks like this:

    public PropertyType __invalid_name__my-invalid-identifier { get; set; }
    

    Of course this will not compile, so you need to notice any __invalid_name properties and manually fix the generated code. Options for doing this include those covered in How can I parse a JSON string that would cause illegal C# identifiers? and elsewhere:

You seem to have encountered both limitations. Working sample .Net fiddle.

dbc
  • 104,963
  • 20
  • 228
  • 340