1

I am using Utf8 json library to deserialize my JSON using DeserializeAsync method of JsonSerializer class. And sometimes I am seeing it is throwing exception as -

Arithmetic operation resulted in an overflow.

So it looks like my JSON data has a value that's too large to fit in one of our object's properties causing this overflow exception. Below is the code I had originally and we weren't catching any exception being thrown from below code -

using (var content = httpResponseMessage.Content)
{
    if (content == null) return (default(T), statusCode);

    using (var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync())
    {
        deserializedValue = await JsonSerializer.DeserializeAsync<T>(responseStream, formatResolver);
    }
}

So now I wrapped my above code in a try catch so that I can catch the exception instead of throwing it and log the body of the request as well -

using (var content = httpResponseMessage.Content)
{
    if (content == null) return (default(T), statusCode);

    using (var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync())
    {
        try
        {
            deserializedValue = await JsonSerializer.DeserializeAsync<T>(responseStream, formatResolver);
        }
        catch (JsonParsingException ex)
        {
            var bodyString = ex.GetUnderlyingByteArrayUnsafe();
            var error = (bodyString != null) ? $"Failing json: {bodyString}" : null;
            logger.logError(error, ex.Message, "Deserialization Exception", ex.StackTrace, (int)statusCode);
            return (default(T), HttpStatusCode.BadRequest);
        }
        catch (Exception ex)
        {
            logger.logError("Cannot Deserialize JSON", ex.Message, "Deserialization Exception", ex.StackTrace, (int)statusCode);
            return (default(T), HttpStatusCode.BadRequest);
        }
    }
}

Problem Statement

I wanted to see if there is any way to combine above two catch block and write it in one inside Exception block? I tried with below code but it complains on this line ex.GetUnderlyingByteArrayUnsafe() as it cannot find GetUnderlyingByteArrayUnsafe method for it. My idea is to log the request if it cannot deserialize the json and write in one catch block if possible.

catch (Exception ex)
{
    var bodyString = ex is JsonParsingException? ex.GetUnderlyingByteArrayUnsafe() : null;
    var error = (bodyString != null) ? $"Failing json: {bodyString}" : "Cannot Deserialize JSON";
    logger.logError(error, ex.Message, "Deserialization Exception", ex.StackTrace, (int)statusCode);
    return (default(T), HttpStatusCode.BadRequest);
}

Also I was looking at the Utf8 json git repo and I don't see DeserializeAsync method throws any JsonParsingException exception?

AndyP
  • 527
  • 1
  • 14
  • 36

1 Answers1

1

The is operator is performing a boolean operation on whether or not your exception can be converted to the target type, but that type conversion is not then passed to the first branch of your ternary.

You can either recast:

var bodyString = ex is JsonParsingException 
    ? ((JsonParsingException)ex).GetUnderlyingByteArrayUnsafe() 
    : null;

Or you can use the as operator which will attempt to make the conversion for you and if it cannot, will return null:

var jsonParsingException = ex as JsonParsingException;
var bodyString = jsonParsingException != null
    ? jsonParsingException.GetUnderlyingByteArrayUnsafe() 
    : null;

Note that with C#7 pattern matching, you can also output the result to a temporary local variable and enable a one-liner:

var bodyString = ex is JsonParsingException j
    ? j.GetUnderlyingByteArrayUnsafe() 
    : null;

and finally, @mjwills pointed out that you can wrap the as operation in braces and check for null with the null propagation operator, allowing for a one-liner as well:

var bodyString = (ex as JsonParsingException)?.GetUnderlyingByteArrayUnsafe();
David L
  • 32,885
  • 8
  • 62
  • 93
  • Thank you! Now I got it how to write it. Also I was looking at Utf8 json [git repo](https://github.com/neuecc/Utf8Json), I don't see `DeserializeAsync` method throws any `JsonParsingException` exception? I just wanted to make sure it will catch it if that method throw the exception when it cannot parse the json. – AndyP Oct 30 '20 at 23:30
  • DeserializeAsync will not _directly_ throw, but the underlying `JsonReader` absolutely does. You can see that the `JsonParsingException` local method is defined here: https://github.com/neuecc/Utf8Json/blob/master/src/Utf8Json/JsonReader.cs#L44 and referenced numerous times throughout the `JsonReader` class. – David L Oct 30 '20 at 23:34
  • Aah now it makes sense. I was looking at `DeserializeAsync` so that's why missed it. Thanks for the link. Appreciate it. – AndyP Oct 30 '20 at 23:35