5

I have the following Json response:

{
  "Customers": [
    {
      "Customer": {
        "Address": {
          "City": "Stockholm",
          "PostalCode": "10123"
        },
        "Classifications": [
          "LoyaltyProgram",
          "Returning",
          "VeryImportant"
        ],
        "FirstName": "Peter",
        "LastName": "Centers",
        "Passport": {
          "Expiration": "2019-01-14",
          "Number": "1564931321655"
        },
      },
      "FirstName": "Peter",
      "LastName": "Centers",
      "Reservation": {
        "AdultCount": 2,
        "AssignedSpaceId": "03f59360-8644-4e29-927a-ad85a6514466",
      },
      "RoomNumber": "302"
    },
  ]
}

I have the following classes for every Customer:

public class CustomerDto
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<string> Classifications { get; set; }
    public PassportDto Passport { get; set; }
    public AddressDto Address { get; set; }
}

public class AddressDto
{
    public string City { get; set; }
    public string PostalCode { get; set; }
}

public class PassportDto
{
    public string Expiration { get; set; }
    public string Number { get; set; }
}

from this I use Json.Net and the following code from one of my methods (extract) where customers below is the response:

var jsonCustomers = JObject.Parse(customers)["Customers"].Children().ToList();
IList<CustomerDto> customerList = new List<CustomerDto>();
foreach (var item in jsonCustomers) {
    customerList.Add(item.ToObject<CustomerDto>());
}

All the values in CustomerDto are filled except for Address and Passport, that are null, and I can't figure out why.

0

3 Answers 3

6

Add two new classes:

public class CustomersWrapper
{
    public IEnumerable<CustomerWrapper> Customers { get; set; }
}

public class CustomerWrapper
{
    public CustomerDto Customer { get; set; }
}

and then replace all of your existing code with:

        var results = JsonConvert.DeserializeObject<CustomersWrapper>(input);
        var customerList = results.Customers.Select(z => z.Customer).ToList();

This will ensure that standard deserialisation occurs for all objects in the hierarchy.

This is needed due to the odd structure of your JSON. https://stackoverflow.com/a/45384366/34092 is the same basic issue (and may be worth a read) - essentially you shouldn't really have Customers and Customer in your JSON. Without those, you wouldn't need the two wrapper classes I have specified.

You may also wish to avoid specifying FirstName and LastName twice (unnecessarily) in the JSON.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, I'm not taking care of the outer values of FirstName and LastName, just getting the "Customers".
Yes, it worked just perfectly, thanks. :) The Json response comes from another source/company (an online hotel booking system) where I have no control over the code. I agree that the Json response looks a bit odd, and when asked about it they said it looks like this due to backward compatibility.
5

You could create a class which has a list of customers on it:

public class CustomerList
{
    public IList<CustomerDto> Customers { get; set; }
}

And the to deserialize the object just call:

CustomerList jsonCustomers = JsonConvert.DeserializeObject<CustomerList>(customers);
IList<CustomerDto> customerList = jsonCustomers.Customers;

Edit: Didn't notice Customer was a nested property on the list of objects in the json array so need another class wrapping the CustomerDto. @mjwills has posted the full answer.

2 Comments

This is a nice code sample, however doesn't solve the problem that was asked. Adding this code, will still produce Address and Pasport set to Nothing (Null).
Yes, just realised that I missed something with the structure of the json and @mjwills has updated their answer with the correct answer.
2

The AddressDto and PassportDto will not be deserialized, just because you are deserializing at one level up in your JSON graph.

Write a class like:

public class WrapCustomer
{
        public CustomerDto Customer { get; set; }
}

Then deserialize this in your for-loop:

customerList.Add(item.ToObject<WrapCustomer>());

Now you will see everything is populated as you expected.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.