0

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.

Wayne Molina
  • 19,158
  • 26
  • 98
  • 163
  • 1
    You **should** represent each address type. You can sum up equal fields in the base class, but do not try to create one superior address class for everything. This keeps everything clean and updatable, when one of these classes are changing someday. I can tell you this, because I integrated a lot of APIs already. :) – Teneko Oct 18 '17 at 13:27
  • You could use the generic response object, but you would need to create a custom deserialiser. JSON.Net supports this and it's not too difficult to do. – DavidG Oct 18 '17 at 13:32

0 Answers0