'Agnostic Deserializing with System.Text.Json

I'm developping an API client to retrieve json data and try to deserialize it to an object.

The API can return the expected object or an error object:

{ "prop1": "value1", "prop2":"value2" }

{ "error": "PLS123", "message":"position laterale de securite" }

So I'd like to deserialize it to instances of the following classes:

public class Foo {
  public string prop1 {get;set;}
  public string prop2 {get;set;}
}

public class Error {
  public string error {get;set;}
  public string message {get;set;}
}

What I tried first is to expect the deserialization would throw an exception when trying to deserialize an error to a Foo:

string jsonContent = ApiCall();
Foo foo = null;
Error err = null;

try
{
  foo = JsonSerializer.Deserialize<Foo>(jsonContent);
}
catch
{
  err = JsonSerializer.Deserialize<Error>(jsonContent);
}

But no exception is raised in this case and I get a Foo with null properties.

Then, I tried to deserialize as a JsonDocument to check error property presence:

JsonDocument jsonDoc = JsonDocument.Parse(jsonContent);
Foo foo = null;
Error err = null;

if (jsonDoc.RootElement.TryGetProperty("error", out JsonElement jsonErr))
{
    err = JsonSerializer.Deserialize<Error>(jsonContent);
}
else
{
    foo = JsonSerializer.Deserialize<Foo>(jsonContent);
}

This is working but it takes much more time to parse and deserialize.

So, is there a fast way to detect which class to deserialize to?



Solution 1:[1]

In your case to avoid the additional check for property (extra parsing), I would create a single class for the result:

public class Result {
  public string prop1 { get; set; }
  public string prop2 { get; set; }

  public string error { get; set; }
  public string message { get; set; }

  public bool IsError { get { return !string.IsNullOrEmpty(error); } }
}

Then, in your logic, first you check result.IsError and then handle the result differently.

In my opinion, the question is also in clear separation between receiving result and then using it. For example, to avoid slowdown on extra parsing, you can always deserialize into single Result instance, and then, depends on content of its properties, return either Error or Foo instance.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1