Home > OS >  Try to serialize the response in two different models
Try to serialize the response in two different models

Time:09-07

I am trying to handle response that is different from what I expect normally. Normally I would expect a response that looks like the Item model below:

  public class Item
  {
    public string Response { get; set; }
    public string StatusCode { get; set; }
  }

But if the DB is down or not responding, it returns this type of answer as seen from the DbError model below:

public class DbError
  {
    public string Code { get; set; }
    public string Title { get; set; }
    public string Message { get; set; }
    public string ErrorCode { get; set; }
    public string Cause { get; set; }
  }

Typically I would try to serialize the response like this:

Item? response = JsonSerializer.Deserialize<Item>(jsonString);

How can I try to serialize as an Item but in case that the db is returning the error, serialize with the DbError model?

CodePudding user response:

There are at least two options. Assuming default System.Text.Json is used to handle json - either write custom converter similar to one in this answer (existence of a property should be used as discriminant not a property value as in that answer) or deserialize dynamically. For example using JsonNode API which became available since .NET 6 (docs):

var doc = JsonSerializer.Deserialize<JsonObject>(jsonString))
if (doc.ContainsKey("response")) 
{
    var item = doc.Deserialize<Item>();
}
else
{
    var error = doc.Deserialize<DbError>();
} 

For earlier versions:

using var doc = JsonSerializer.Deserialize<JsonDocument>(jsonString);
if (doc.RootElement.TryGetProperty("response", out var _))
{
    var item = doc.Deserialize<Item>();
}
else
{
    var error = doc.Deserialize<DbError>();
}

If you are using Newtonsoft's Json.NET both approaches can be implemented with it too.

CodePudding user response:

you'd need what is normally called "envelope". Don't return your item directly, but wrap it into another object. Something like this:

public class Envelope<T>
{
   public T Data {get;}
   public Error Error {get;}
   public bool IsSuccessful => (this.Error is null);
}

your API consumer would have to check if IsSuccessful is true and otherwise inspect the contents of the Error property.

  • Related