0

I'm using Json.NET to deserialize the response from a third party restful API (don't have control over this and unfortunately can't use a different one). The API returns either a response object or an error object.

At the moment both my response and error objects inherit from a base object and I deserialize to that and then cast to the type that it is.

var response = JsonConvert.DeserializeObject<BaseMessage>(responseContent);

switch (response)
{
    case ResponseMessage responseMessage:
        return responseMessage;
    case ErrorMessage error:
        return error;
}

The ResponseMessage and ErrorMessage are nothing alike, nor contain a field that says which type it is. I just know from the schema. Imagine they're like the following.

public class BaseMessage
{
}

public class ResponseMessage : BaseMessage
{
    public string Status { get; set; }
    public string Reference { get; set; }
}

public class ErrorMessage : BaseMessage
{ 
    public string ErrorCode { get; set; }
    public string ErrorMessage { get; set; }
}

The only reason that they both inherit from BaseMessage is so that I can deserialize to that type and then cast to the type that it actually should be.

Is there a better way of knowing which object the JSON should deserialize to?

GMon
  • 638
  • 6
  • 14

2 Answers2

0

I usually make a standard response that looks as follows:

For success:

{
 "status": 200,
 "message": "Stored Successfully!",
 "result" : {
     "some_attr": "some value",
  }
}

For Failure:

{
 "status": 302, //or any other standard response code
 "message": "Token missing", //Any other error message
 "result" : {
     // error object or empty result if no need to add details to error.
  }
}

So now all you need is to deserialize/serialize to an object that looks like:

int status;
string message;
dynamic result;

and you get the rest of the scenario.

Edit:

For APIs that do not support this kind of format and you have no control over it, you can either pick an attribute in the success object to manually check for it's existence using JObject.

Or try deserializing to success object else, deserialize to error object on exception (this feels a little bit hacky but a third part api that does not provide a standard HTTP Response will force you to use such hacks anyways).

Ramy M. Mousa
  • 5,727
  • 3
  • 34
  • 45
0

You would probably need to inspect the response first before deserializing to the desired type

//...

var response = JObject.Parse(responseContent);

if (response.ContainsKey("ErrorCode")) { //Or what ever the actual key is
    return response.ToObject<ErrorMessage>();
}

if (response.ContainsKey("Status")) { //Or what ever the actual key is
    return response.ToObject<ResponseMessage>();
}

//...

The above uses JObject to parse the response and inspect the keys to determine what type to parse the response.

Nkosi
  • 235,767
  • 35
  • 427
  • 472