-1

when do a POST request to a web API the response could be returned in two ways:

{
"Response": {
    "StatusCode": 200,
    "StatusMessage": "OK",
    "Content": {
        "auth_hash": "606ca0e7802a070531b4b2fd8ee5fc17b4649a19"
    }
  }
}

or

{
"Response": {
    "StatusCode": 200,
    "StatusMessage": "OK",
    "Content": {
        "document": {
             "loja": 5,
            "numero": 85099,
            "doc": "FS",
            "data": "2017-12-13",
            "cliente": 0,
            "nome": "CONSUMIDOR FINAL",
            "liquido": 1.1504,
            "total": 1.3,
            "anulado": 0,
            "emp": 5,
            "pago": 1,
            "datapag": "2017-12-13",
            "tipo": 0,
            "pagamento": 1,
            "datahora": "2017-12-13 12:51:51",
            "deve": 0,
            "idcx": 240403,
            "mesa": 1001,
            "mesaidx": 0,
            "lugar": 0
        }
    }
  }
}

How can I deserialize the value "Content" into a C# class object being this values variable?

Best Regards

Pedro Costa
  • 199
  • 8
  • When calling the API, do you know what will be inside the `Content` node? – CodeCaster Dec 13 '17 at 13:09
  • this are two different response, you need two diffrent content class fo this o – Pranay Rana Dec 13 '17 at 13:10
  • Just to clarify - these 2 responses are from the exact same call? As in a call to `api/route1` could return *either* of those responses? – Jamiec Dec 13 '17 at 13:11
  • Check out [this answer](https://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object) about [dynamic](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic) – Peter Szekeli Dec 13 '17 at 13:11
  • @CodeCaster - in that case he has to create content class which include property of both response – Pranay Rana Dec 13 '17 at 13:11
  • @Pranay no, they can't, because it's the same node, namely `Content`. They could solve it using generics and specifying the child element type, but whether that's viable depends on the answer to the first comment. – CodeCaster Dec 13 '17 at 13:11
  • @Szeki - no there is no need of dynamic as response is one of two – Pranay Rana Dec 13 '17 at 13:12
  • @CodeCaster - in Content class which get created in C# need to include all property of first reposen auth_hash+ property of content second response – Pranay Rana Dec 13 '17 at 13:13
  • @Pranay yeah and then do a null check? What if there's five different response types? Do five null checks? What if some responses share some of the same properties, but not all? – CodeCaster Dec 13 '17 at 13:14
  • @CodeCaster - here is two reponse fixed ...and dynamic is more dangerous than this – Pranay Rana Dec 13 '17 at 13:15

2 Answers2

3

I assume you know which call can return which response. Then a solution could be to create a generic container, and provide the expected type as generic argument. So the container looks like this:

public class ResponseContainer<TContent>
{
    public Response<TContent> Response { get; set; }
}

public class Response<TContent>
{
    public int StatusCode { get; set; }
    public string StatusMessage { get; set; }
    public TContent Content { get; set; }
}

Then you create (or rather, generate) a class per response type:

public class DocumentContent
{
    public Document document { get; set; }
}

public class Document
{
    public int loja { get; set; }
    // ...
    public int lugar { get; set; }
}

Then you can deserialize into the type you want, by varying the TContent argument, in this case DocumentContent:

string json = PerformDocumentCall();
var deserialized = JsonConvert.DeserializeObject<ResponseContainer<DocumentContent>>(json);

And for the auth response you pass AuthContent:

public class AuthContent
{
    public string auth_hash { get; set; }
}

string json = PerformAuthCall();
var deserialized = JsonConvert.DeserializeObject<ResponseContainer<AuthContent>>(json);
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • How he got to know that he is going to receive reponse 1 or response 2 ..that confuse me ...you may be correct if he knows in adavace – Pranay Rana Dec 13 '17 at 13:22
  • See sentence one of my answer. I assume they do. – CodeCaster Dec 13 '17 at 13:22
  • @PranayRana I think this assumes you know which call you're making - which is the usual state of affairs when using an API. It would be weird for a single call to return 2 very different (success/200) responses – Jamiec Dec 13 '17 at 13:22
  • I do agree with you...it look better ....it could be problem if reponse is dynamic...thats it – Pranay Rana Dec 13 '17 at 13:23
  • @Jamiec - yes that may be case in that case solution is good ...but if method is returning two different reponse than...in webAPI you can return HttPResponse which can be dynamic ... – Pranay Rana Dec 13 '17 at 13:25
  • 1
    @PranayRana at which point you ask the api author to return sensible responses, or use a different one. – Jamiec Dec 13 '17 at 13:26
  • @Jamiec - based on if ..else ..condition, may be author return two diffrent response ...like if authorized use get one reponse and not authorized get another response ... – Pranay Rana Dec 13 '17 at 13:29
  • @PranayRana There are httpstatus codes for that - both of these are success/200 responses. That would be an odd implementation. – Jamiec Dec 13 '17 at 13:30
0

Apart from reading and parsing the raw string and looking for clues, a very easy way is to simply deserialize into one POCO first (using Json.NET or similar). If all values are empty, you try the next type. The order in which you deserialize could be decided out from what's most common or expected in the specific use case.

Or, if you feel slightly more adventurous you could deserialize it into a dynamic, and simply check if response.Content.document exists. Very little code, but not as "strict" as above.

Arve Systad
  • 5,471
  • 1
  • 32
  • 58
  • Possible with limitless returntypes, but of course this would be inefficient. Unless the API you're calling can tell you what type to expect, (or it can be inferred from context, or the like), you'll end up with some checking on your side no matter what. Shit in => Shit out. – Arve Systad Dec 14 '17 at 11:29
  • I would gladly take an explanation from whoever gave me the downvote anyways. My answer *is* true, and *will* work. – Arve Systad Dec 14 '17 at 11:30