0
votes

Below is a JSON response from a REST API call I make in a Windows Store App (Win 8.1). It contains a page of results from the REST API call, with each result (row) being a PropertyMaster record/object. Included below that is the JSON classes Visual Studio 2013 created using the Paste Special as JSON IDE feature. As you can see the PropertyMaster object has an addresses field that is an array of Address objects. If you look at the JSON you will see the first result does have a valid Address object inside the addresses JSON array. However, when I deserialize the JSON response using the following call:

JsonConvert.DeserializeObject<PropertyRecordsResponse>(json);

The addresses field in the PropertyMaster object is NULL. I am not getting any Exceptions thrown by JSON.NET so why isn't the contents of the addresses JSON array being parsed properly into an array of Address objects? Any tips on how to track down and fix this problem are appreciated.

NOTE: I did find this SO post on deserializing a nested array of objects:

Deserializing json string with array of array with Json.NET

But I swear I've had nested arrays of objects before in JSON and have not needed to take special actions to deserialize them.

JSON RESPONSE FROM API CALL

{
    "page": {
        "totalRows": 13
    },
    "records": [
        {
            "display": "14CAP-00000005",
            "module": "Building",
            "assignToInfo": {
                "totalJobCost": "0.0"
            },
            "id": "DUB14-00000-0000I",
            "type": {
                "id": "Building-Mobile-Mobile-Tony",
                "display": "Building/Mobile/Mobile/Tony"
            },
            "status": {
                "id": "Ready.cto.cIssue",
                "display": "Ready to Issue"
            },
            "openDate": "2014-08-07"
        },
        {
            "display": "14CAP-00000006",
            "module": "Building",
            "assignToInfo": {
                "totalJobCost": "0.0"
            },
            "id": "DUB14-00000-0000J",
            "type": {
                "id": "Building-Mobile-Mobile-Tony",
                "display": "Building/Mobile/Mobile/Tony"
            },
            "status": {
                "id": "Ready.cto.cIssue",
                "display": "Ready to Issue"
            },
            "openDate": "2014-08-07"
        },
        {
            "addresses": [
                {
                    "id": "999974830-924597381",
                    "display": "233 Camino Ramon Suite 500, San Ramon, CA, 94583",
                    "houseNumber": "233",
                    "streetName": "Camino Ramon",
                    "unit": "500",
                    "unitType": "Suite",
                    "state": "CA",
                    "postalCode": "94583",
                    "city": "San Ramon",
                    "isPrimary": "True",
                    "enabled": true,
                    "entityState": "Unchanged"
                }
            ]
        }
    ]
}

Classes created by VS2013 for deserialization

public class PropertyRecordsResponse
{
    public Page page { get; set; }
    public PropertyMaster[] records { get; set; }

    /// <summary>
    /// Deserializes a JSON response from an Accela API call into a property records response object (and sub-objects).
    /// </summary>
    /// <param name="json">The JSON response in string form.</param>
    public static PropertyRecordsResponse ParseJSON(string json)
    {

        return JsonConvert.DeserializeObject<PropertyRecordsResponse>(json);
    }
}

/// <summary>
/// One page of results as returned by an Accela REST API method that returns property records.
/// </summary>
public class Page
{
    public int totalRows { get; set; }
    public bool hasMore { get; set; }
}

public class PropertyMaster
{
    public Address[] addresses { get; set; }
    public string display { get; set; }
    public string module { get; set; }
    public string name { get; set; }
    public Assigntoinfo assignToInfo { get; set; }
    public User user { get; set; }
    public string createdDate { get; set; }
    public string id { get; set; }
    public string description { get; set; }
    public bool isPrivate { get; set; }
    public RecType type { get; set; }
    public Status status { get; set; }
    public Department department { get; set; }
    public Staffperson staffPerson { get; set; }
    public string assignDate { get; set; }
    public string scheduleDate { get; set; }
    public string scheduleTime { get; set; }
    public string openDate { get; set; }
    public string priority { get; set; }
    public string shortNotes { get; set; }
    public string templateName { get; set; }
}

public class Assigntoinfo
{
    public string totalJobCost { get; set; }
    public string completeDate { get; set; }
    public string AssignDate { get; set; }
    public string scheduledDate { get; set; }
    public string assignStaff { get; set; }
    public string assignDepartment { get; set; }
    public string priority { get; set; }
}

public class User
{
    public string firstName { get; set; }
    public string lastName { get; set; }
    public string civicId { get; set; }
    public string email { get; set; }
}

public class RecType
{
    public string id { get; set; }
    public string display { get; set; }
    public string module { get; set; }
    public string group { get; set; }
    public string subGroup { get; set; }
    public string category { get; set; }
    public string type { get; set; }
    public string security { get; set; }
    public string[] inspectionGroups { get; set; }
    public string[] standardCommentsGroupIds { get; set; }
}

public class Status
{
    public string id { get; set; }
    public string display { get; set; }
}

public class Department
{
    public string id { get; set; }
    public string display { get; set; }
    public string agency { get; set; }
    public string bureau { get; set; }
    public string division { get; set; }
    public string section { get; set; }
    public string group { get; set; }
    public string subGroup { get; set; }
    public string subGroupDescription { get; set; }
}

public class Staffperson
{
    public string id { get; set; }
    public string display { get; set; }
    public string agencyCode { get; set; }
    public string auditStatus { get; set; }
    public string bureauCode { get; set; }
    public string divisionCode { get; set; }
    public string firstName { get; set; }
    public string groupCode { get; set; }
    public string lastName { get; set; }
    public string officeCode { get; set; }
    public string sectionCode { get; set; }
    public string serviceProviderCode { get; set; }
    public string userStatus { get; set; }
}

public class Address
{
    public string id { get; set; }
    public string display { get; set; }
    public string addressFormat { get; set; }
    public string houseNumber { get; set; }
    public string houseNumberFraction { get; set; }
    public string streetDirection { get; set; }
    public string streetName { get; set; }
    public string streetSuffix { get; set; }
    public string streetSuffixDirection { get; set; }
    public string unit { get; set; }
    public string unitEnd { get; set; }
    public string unitType { get; set; }
    public string state { get; set; }
    public string postalCode { get; set; }
    public string city { get; set; }
    public string county { get; set; }
    public string country { get; set; }
    public string isPrimary { get; set; }
    public string xCoordinate { get; set; }
    public string yCoordinate { get; set; }
    public bool enabled { get; set; }
    public string entityState { get; set; }
}
1
How about posting a valid json?L.B
@L.B - I've added the raw JSON result to my post, below the formatted result. Look for the line "RAW JSON RESULT". Thanks. If there any other problems with it, then it's because I deleted the other rows from the result for brevity. The first row is intact.Robert Oschler
Yeah, the JSON is invalid. Also, having a class named "Type" may make your life difficult.Slippery Pete
The raw JSON is still invalid according to jsonformatter.curiousconcept.com. I got it to validate by adding a ] before the final }, but I do not know if this is the intent.Slippery Pete
@RobertOschler I put your json to json2csharp.com and deserialized using that classes. Your root object has only 3 records and only one of them has addresses field (and only that field).L.B

1 Answers

1
votes

It looks like the address is not in the right place in the JSON. Try deserializing this (the address is in the second record):

{
   "page":{
      "totalRows":1
   },
   "records":[
      {
         "display":"14CAP-00000005",
         "module":"Building",
         "assignToInfo":{
            "totalJobCost":"0.0"
         },
         "id":"DUB14-00000-0000I",
         "type":{
            "id":"Building-Mobile-Mobile-Tony",
            "display":"Building/Mobile/Mobile/Tony"
         },
         "status":{
            "id":"Ready.cto.cIssue",
            "display":"Ready to Issue"
         },
         "openDate":"2014-08-07"
      },
      {
         "display":"14CAP-00000006",
         "module":"Building",
         "assignToInfo":{
            "totalJobCost":"0.0"
         },
         "id":"DUB14-00000-0000J",
         "type":{
            "id":"Building-Mobile-Mobile-Tony",
            "display":"Building/Mobile/Mobile/Tony"
         },
         "status":{
            "id":"Ready.cto.cIssue",
            "display":"Ready to Issue"
         },
         "openDate":"2014-08-07",
         "addresses":[
            {
               "id":"999974830-924597381",
               "display":"233 Camino Ramon Suite 500, San Ramon, CA, 94583",
               "houseNumber":"233",
               "streetName":"Camino Ramon",
               "unit":"500",
               "unitType":"Suite",
               "state":"CA",
               "postalCode":"94583",
               "city":"San Ramon",
               "isPrimary":"True",
               "enabled":true,
               "entityState":"Unchanged"
            }
         ]
      }
   ]
}