Reputation: 265
I'm trying to deserialize a JSON object that may or may not have items with certain attributes.
Here's an example, someone can have none or many phone numbers.
"PhoneNumbers": [
{
"PhoneId": 190434,
"PhoneNumber": "213-555-0001",
"PhoneExtension": null,
"PhoneType": {
"@odata.type": "#Enterprise.Contracts.DataContracts.Party.PhoneType",
"PhoneTypeId": 18,
"PhoneTypeAbbreviation": null,
"PhoneTypeCode": "MOBILE",
"PhoneTypeName": "MOBILE PHONE",
"PhoneTypeDescription": "MOBILE PHONE"
}
},
{
"PhoneId": 190436,
"PhoneNumber": "213-555-0003",
"PhoneExtension": null,
"PhoneType": {
"@odata.type": "#Enterprise.Contracts.DataContracts.Party.PhoneType",
"PhoneTypeId": 16,
"PhoneTypeAbbreviation": null,
"PhoneTypeCode": "FAX",
"PhoneTypeName": "FACSIMILE",
"PhoneTypeDescription": "FACSIMILE"
}
},
{
"PhoneId": 190437,
"PhoneNumber": "213-555-0004",
"PhoneExtension": 50004,
"PhoneType": {
"@odata.type": "#Enterprise.Contracts.DataContracts.Party.PhoneType",
"PhoneTypeId": 14,
"PhoneTypeAbbreviation": null,
"PhoneTypeCode": "OFFICE",
"PhoneTypeName": "OFFICE PHONE",
"PhoneTypeDescription": "OFFICE PHONE"
}
}
],
Some people instead of having a MOBILE PHONE may have a BLACKBERRY, and vise-versa. They could even have both. Here's how I'm trying to get those attributes.
if (item.PhoneNumbers != null)
{
Output0Buffer.OfficePhone = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "OFFICE").FirstOrDefault().PhoneNumber;
Output0Buffer.MobilePhone = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "MOBILE").FirstOrDefault().PhoneNumber;
Output0Buffer.BlackBerry = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "BLKBRRY").FirstOrDefault().PhoneNumber;
Output0Buffer.Fax = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "FAX").FirstOrDefault().PhoneNumber;
Output0Buffer.Extension = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "OFFICE").FirstOrDefault().PhoneExtension.ToString();
}
The problem I'm having is if someone doesn't have a Blackberry or they don't have a MOBILE PHONE
, etc. I'm getting a null value exception.
I have my serializer settings to ignore null values, but I still seem to get the exception.
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
var results = JsonConvert.DeserializeObject<ODataResponse>(json,settings);
Any thoughts on how I can change that LINQ where clause to support this?
EDIT: This method here seems to work. I didn't know if there was a better way of handling this so I didn't have to wrap it around every attribute
if (item.PhoneNumbers != null)
{
string officePhone = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "OFFICE").Select(s => s.PhoneNumber).FirstOrDefault();
if (officePhone != null)
Output0Buffer.OfficePhone = officePhone;
string mobilePhone = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "MOBILE").Select(s => s.PhoneNumber).FirstOrDefault();
if (mobilePhone != null)
Output0Buffer.MobilePhone = mobilePhone;
string blackBerry = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "BLKBRRY").Select(s => s.PhoneNumber).FirstOrDefault();
if (blackBerry != null)
Output0Buffer.BlackBerry = blackBerry;
string fax = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "FAX").Select(s => s.PhoneNumber).FirstOrDefault();
if (fax != null)
Output0Buffer.Fax = fax;
string extension = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "OFFICE").Select(s => s.PhoneExtension).FirstOrDefault().ToString();
if (extension != null)
Output0Buffer.Extension = extension;
}
Upvotes: 1
Views: 1592
Reputation: 466
I have used this WhereIf(bCondition, expression) extention method to accomplish what you're trying to do:
public static IEnumerable<TSource> WhereIf<TSource>(this IEnumerable<TSource> source, bool condition, Func<TSource, bool> predicate)
{
if (condition)
return source.Where(predicate);
else
return source;
}
public static IEnumerable<TSource> WhereIf<TSource>(this IEnumerable<TSource> source, bool condition, Func<TSource, int, bool> predicate)
{
if (condition)
return source.Where(predicate);
else
return source;
}
See this link for more information:
http://extensionmethod.net/csharp/ienumerable-t/whereif
Upvotes: 0
Reputation: 129827
FirstOrDefault()
will return null
if there is no item matching the Where
clause. So if you try to deference that return value directly, then of course you will get an exception when it is null.
Try using Select
after the Where
to project to the result you want before using FirstOrDefault()
, e.g.:
Output0Buffer.BlackBerry = item.PhoneNumbers
.Where(p => p.PhoneType.PhoneTypeCode == "BLKBRRY")
.Select(p => p.PhoneNumber)
.FirstOrDefault();
Upvotes: 1
Reputation: 4194
The problem is that FirstOrDefault()
may return null, so FirstOrDefault().PhoneNumber
will throw an exception.
If you are using C# 4.6, you can do this (notice the ?
):
Output0Buffer.OfficePhone = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "OFFICE").FirstOrDefault()?.PhoneNumber;
Otherwise, you could do this instead:
if (item.PhoneNumbers != null)
{
Output0Buffer.OfficePhone = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "OFFICE").Select(p => p.PhoneNumber).FirstOrDefault();
Output0Buffer.MobilePhone = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "MOBILE").Select(p => p.PhoneNumber).FirstOrDefault();
Output0Buffer.BlackBerry = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "BLKBRRY").Select(p => p.PhoneNumber).FirstOrDefault();
Output0Buffer.Fax = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "FAX").Select(p => p.PhoneNumber).FirstOrDefault();
Output0Buffer.Extension = item.PhoneNumbers.Where(p => p.PhoneType.PhoneTypeCode == "OFFICE").Select(p => p.PhoneExtension).FirstOrDefault();
}
Upvotes: 0