简体   繁体   中英

Problems Deserializing Nested JSON Array in C#

Edit I notice this is getting negative votes, I imagine it's for not showing research effort. I've looked at a lot of stack overflow posts. I can't find an example with JSON this heavily nested that has been accessed with examples of how the data stored in the JSON has been manipulated afterwards.

Problem and Aim

Using restsharp I've received a JSON response to an API call I made however I'm struggling to deserialize the response I'm getting. The data I want to use seems to be a nested array (below).

My aim is to then pass the contents of that array to a variable, check if it's populated, take the first item of that array, and then set the properties in that item equal to objects in my database.

This is the error message I'm getting with my current code. It seems like I'm treating the Hit object as the wrong type of object however after a few hours of banging my head against a wall I'm not entirely sure why in particular this isn't working for this particular JSON structure.

Current Code

                    var hitresult = JsonConvert.DeserializeObject( response.Content, typeof( List<Hit> ) ) as List<Hit>;
                    if (hitresult.Any())
                    {
                            var address = hitresult.FirstOrDefault();
                            verified = true;
                            result = string.Format( "UDPRN: {0}", address.udprn ); 
                            location.Street1 = address.line_1;
                            location.Street2 = address.line_2;
                            location.City = address.post_town;
                            location.State = address.county;
                            location.PostalCode = address.postcode;

Error Message

An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code

Additional information: Cannot deserialize the current JSON object (eg {"name":"value"}) into type 'System.Collections.Generic.List`1[org.hopecorby.LocationService.Hit]' because the type requires a JSON array (eg [1,2,3]) to deserialize correctly.

To fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg 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.

Path 'result', line 1, position 10.

Example JSON

 {
    "result": {
        "total": 2,
        "limit": 10,
        "page": 0,
        "hits": [
            {
                "dependant_locality": "",
                "postcode_type": "L",
                "po_box": "",
                "post_town": "LONDON",
                "delivery_point_suffix": "1A",
                "double_dependant_locality": "",
                "su_organisation_indicator": " ",
                "longitude": -0.127695242183412,
                "department_name": "",
                "district": "Westminster",
                "building_name": "",
                "dependant_thoroughfare": "",
                "northings": 179951,
                "premise": "10",
                "postcode_outward": "SW1A",
                "postcode_inward": "2AA",
                "sub_building_name": "",
                "eastings": 530047,
                "postcode": "SW1A 2AA",
                "country": "England",
                "udprn": 23747771,
                "line_3": "",
                "organisation_name": "Prime Minister & First Lord Of The Treasury",
                "ward": "St James's",
                "county": "",
                "line_1": "Prime Minister & First Lord Of The Treasury",
                "building_number": "10",
                "thoroughfare": "Downing Street",
                "line_2": "10 Downing Street",
                "latitude": 51.5035398826274
            },
            {
                "dependant_locality": "",
                "postcode_type": "S",
                "po_box": "",
                "post_town": "LONDON",
                "delivery_point_suffix": "1B",
                "double_dependant_locality": "",
                "su_organisation_indicator": " ",
                "longitude": -0.122624730080001,
                "department_name": "",
                "district": "Camden",
                "building_name": "Downing Court",
                "dependant_thoroughfare": "",
                "northings": 182178,
                "premise": "Flat 10, Downing Court",
                "postcode_outward": "WC1N",
                "postcode_inward": "1LX",
                "sub_building_name": "Flat 10",
                "eastings": 530342,
                "postcode": "WC1N 1LX",
                "country": "England",
                "udprn": 26245117,
                "line_3": "Grenville Street",
                "organisation_name": "",
                "ward": "Bloomsbury",
                "county": "",
                "line_1": "Flat 10",
                "building_number": " ",
                "thoroughfare": "Grenville Street",
                "line_2": "Downing Court",
                "latitude": 51.5234851731108
            }
        ]
    },
    "code": 2000,
    "message": "Success"
}

My Models(Created with json2charp)

public class Hit
{
    public string dependant_locality { get; set; }
    public string postcode_type { get; set; }
    public string po_box { get; set; }
    public string post_town { get; set; }
    public string delivery_point_suffix { get; set; }
    public string double_dependant_locality { get; set; }
    public string su_organisation_indicator { get; set; }
    public double longitude { get; set; }
    public string department_name { get; set; }
    public string district { get; set; }
    public string building_name { get; set; }
    public string dependant_thoroughfare { get; set; }
    public int northings { get; set; }
    public string premise { get; set; }
    public string postcode_outward { get; set; }
    public string postcode_inward { get; set; }
    public string sub_building_name { get; set; }
    public int eastings { get; set; }
    public string postcode { get; set; }
    public string country { get; set; }
    public int udprn { get; set; }
    public string line_3 { get; set; }
    public string organisation_name { get; set; }
    public string ward { get; set; }
    public string county { get; set; }
    public string line_1 { get; set; }
    public string building_number { get; set; }
    public string thoroughfare { get; set; }
    public string line_2 { get; set; }
    public double latitude { get; set; }
}

public class Result
{
    public int total { get; set; }
    public int limit { get; set; }
    public int page { get; set; }
    public List<Hit> hits { get; set; }
}

public class RootObject
{
    public Result result { get; set; }
    public int code { get; set; }
    public string message { get; set; }
}

The Deserializer expects a JSON Array. Your JSON is a JSON Object containing a JSON Array. There's no way the deserializer can know that you expect it to start its work with the hits array.

You need to deserialize as the RootObject. Then you would be able to refer to the List<Hit> as a property of the Result.

Update:

The following code should give you a sense of what I mean. I tested this and it works for me, with your objects and your JSON.

var sr = new StreamReader(@"C:\Users\danielc\Documents\Visual Studio 2012\Projects\TestJSON\TestJSON\response.json");
string json = sr.ReadToEnd();
sr.Close();

var root = JsonConvert.DeserializeObject<RootObject>(json);
var result = root.result;
var hits = result.hits;

if (hits.Any())
{
    var address = hits.FirstOrDefault();
    var udprn = string.Format("UDPRN: {0}", address.udprn);
    Console.WriteLine(udprn);
}

Console.Read();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM