I am working on a program that will need to call a third party API that has been provided to us. We are using Newtonsoft.Json for serializing/deserializing the objects.
I want to create a generic "base" object since from looking at the API all of the calls have some common data (e.g. error code, error message) and then have the relevant data. I have been trying something like this:
JSON Response from API
{
"addressInfo": {
"checksum": "317841",
"homeGeoCode": "",
"homeAddress": {
"addressLine1": "123 MAIN STREET",
"addressLine2": "",
"city": "NEW YORK",
"county": "BRONX",
"stateAbbr": "NY",
"zipCode": "10013",
"zipSuffix": ""
},
"w2Address": {
"addressLine1": "",
"addressLine2": "",
"city": "",
"stateAbbr": "",
"zipCode": ""
},
"altAddress": {
"addressLine1": "",
"addressLine2": "",
"city": "",
"stateAbbr": "",
"zipCode": "0"
}
},
"errorCode": "0",
"errorMessage": ""
}
Now, since there will be many such calls for different API methods, with errorCode
and errorMessage
being common to all of them, I had wanted to create a generic "root" object that could be of any type so each of my "response" classes from the API would have a base type. Something like the following:
Generic Response Object
public abstract class ApiResponse<T>
{
public string ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public T Data { get; set; }
}
So for this example, the request might look like:
Deserializing the Response
var response = JsonConvert.DeserializeObject<ApiResponse<AddressInfo>>(jsonString);
where the AddressInfo class has the subclasses and properties as defined in the JSON (e.g. HomeAddress, W2Address, Checksum, etc.).
However, this doesn't seem to work right because JSON.NET doesn't know that in this case "Data" corresponds to the addressInfo
part of the JSON string, even if the type of T
is set as AddressInfo
.
Is there a way to get this functionality, or should I just make the ApiResponse
class non-generic and ensure that subclasses need to provide the corresponding data type with the correct name (e.g. AddressInfo), for example:
Hypothetical Derived Class
public class GetAddressInfoResponse : ApiResponse
{
// ErrorCode supplied from base
// ErrorMessage supplied from base
public AddressInfo AddressInfo { get; set; }
}
This seems like the easier approach, but also means we specifically need a Response class for every type of request which adds complexity while if the generic response could work, we could just use that and set the type to be each of the data classes that are mapped from the API without having a wrapper class around each.