Reputation: 1565
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.
Upvotes: 5
Views: 12270
Reputation: 23819
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.
Upvotes: 6
Reputation: 2430
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.
Upvotes: 5
Reputation: 486
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.
Upvotes: 2