I am calling contacts from the LightSpeed API.
When i call for the details of client "A" the JSON contains the following for his related email(s)
{
"Emails": {
"ContactEmail": {
"address": "[email protected]",
"useType": "Primary"
}
}
}
When I call for the details of client "B" the JSON contains the following for this related email(s)
{
"Emails": {
"ContactEmail": [{
"address": "[email protected]",
"useType": "Primary"
}, {
"address": "[email protected]",
"useType": "Secondary"
}
]
}
}
If I am correct I believe that the first response should be an array even if there is only 1 "email" returned...? because the system does allow for customers to have more than 1 email in their record.
Here is the class I am trying to Deserialize into. It works perfectly for client "B" but fails for client "A"
public class GetCustomersResponse
{
public Attributes attributes { get; set; }
public List<Customer> Customer { get; set; }
}
public class Attributes
{
public string count { get; set; }
}
public class Customer
{
public string customerID { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string title { get; set; }
public string company { get; set; }
public string companyRegistrationNumber { get; set; }
public string vatNumber { get; set; }
public DateTime createTime { get; set; }
public DateTime timeStamp { get; set; }
public string archived { get; set; }
public string contactID { get; set; }
public string creditAccountID { get; set; }
public string customerTypeID { get; set; }
public string discountID { get; set; }
public string taxCategoryID { get; set; }
public Contact Contact { get; set; }
}
public class Contact
{
public string contactID { get; set; }
public string custom { get; set; }
public string noEmail { get; set; }
public string noPhone { get; set; }
public string noMail { get; set; }
public Addresses Addresses { get; set; }
public Phones Phones { get; set; }
public Emails Emails { get; set; }
public string Websites { get; set; }
public DateTime timeStamp { get; set; }
}
public class Addresses
{
public Contactaddress ContactAddress { get; set; }
}
public class Contactaddress
{
public string address1 { get; set; }
public string address2 { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
public string country { get; set; }
public string countryCode { get; set; }
public string stateCode { get; set; }
}
public class Phones
{
public List<Contactphone> ContactPhone { get; set; }
}
public class Contactphone
{
public string number { get; set; }
public string useType { get; set; }
}
public class Emails
{
public List<Contactemail> ContactEmail { get; set; }
}
public class Contactemail
{
public string address { get; set; }
public string useType { get; set; }
}
I can't see me getting LightSpeed to change their API so can anyone suggest how to get the client with 1 email address to work with my class?
Any help would be greatly appreciated.
UPDATE:
with the help given I have got very close to some working code.
this is what I have for the custom json convertor:
public class ContactEmailJsonConverter : JsonConverter<List<ContactEmail>>
{
public override List<ContactEmail> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
try
{
if (reader.TokenType == JsonTokenType.StartArray)
{
return (List<ContactEmail>)JsonSerializer
.Deserialize(ref reader, typeToConvert, options);
}
else if (reader.TokenType == JsonTokenType.StartObject)
{
var email = (ContactEmail)JsonSerializer
.Deserialize(ref reader, typeof(ContactEmail), options);
return new List<ContactEmail>(capacity: 1) { email };
}
else
{
throw new InvalidOperationException($"got: {reader.TokenType}");
}
}
catch(Exception ex)
{
return null;
}
}
public override void Write(Utf8JsonWriter writer, List<ContactEmail> value, JsonSerializerOptions options)
{
if ((value is null) || (value.Count == 0))
{
JsonSerializer.Serialize(writer, (ContactEmail)null, options);
}
else if (value.Count == 1)
{
JsonSerializer.Serialize(writer, value[0], options);
}
else
{
JsonSerializer.Serialize(writer, value, options);
}
}
}
But, I have now found a contact which appears not to have an email at all.. And the JSON returned by LightSpeed looks like this:
"Emails":""
and it's breaking the converter code I have written. I am not sure how to handle this completely empty object?
What you are going to have to do is create a couple custom
JsonConverter
objects. Let's say your models look like this:First, you need to set up a custom converter to handle
List<ContactEmail>
and the weird instances where it could be an array or single object:Second, you need to set up a custom converter to handle
Emails
and the weird instances where it's not an actualEmails
object:Then you'd add the converters to your models:
And simply deserialize as normal: