【问题标题】:Check for exception type inside Exception catch block and log it检查异常捕获块中的异常类型并记录它
【发布时间】:2020-10-30 23:00:36
【问题描述】:

我正在使用 Utf8 json 库使用 DeserializeAsync 类的 DeserializeAsync 方法反序列化我的 JSON。有时我看到它抛出异常 -

Arithmetic operation resulted in an overflow.

所以看起来我的 JSON 数据的值太大而无法放入我们对象的某个属性中,从而导致此溢出异常。下面是我最初的代码,我们没有捕捉到从下面的代码抛出的任何异常 -

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);
    }
}

所以现在我将上面的代码包装在一个 try catch 中,这样我就可以捕获异常而不是抛出它并记录请求的主体 -

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);
        }
    }
}

问题陈述

我想看看有没有办法把上面的两个catch块合并到一个Exception块里面?我尝试使用下面的代码,但它在ex.GetUnderlyingByteArrayUnsafe() 这一行抱怨,因为它找不到GetUnderlyingByteArrayUnsafe 方法。我的想法是在请求无法反序列化 json 时记录该请求,并尽可能写入一个 catch 块。

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);
}

我还在查看 Utf8 json git repo,但我没有看到 DeserializeAsync 方法抛出任何 JsonParsingException 异常?

【问题讨论】:

  • var bodyString = (ex as JsonParsingException)?.GetUnderlyingByteArrayUnsafe();

标签: c# json utf8json


【解决方案1】:

is 运算符正在对您的异常是否可以转换为目标类型执行布尔运算,但该类型转换不会随后传递到三元组的第一个分支。

你可以重铸:

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

或者您可以使用as 运算符,它将尝试为您进行转换,如果不能,将返回 null:

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

请注意,使用C#7 pattern matching,您还可以将结果输出到临时局部变量并启用单线:

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

最后,@mjwills 指出,您可以将 as 操作包装在大括号中,并使用 null 传播运算符检查 null,也允许单行:

var bodyString = (ex as JsonParsingException)?.GetUnderlyingByteArrayUnsafe();

【讨论】:

  • 谢谢!现在我知道怎么写了。我也在看 Utf8 json git repo,我没有看到 DeserializeAsync 方法抛出任何 JsonParsingException 异常?我只是想确保如果该方法在无法解析 json 时抛出异常,它会捕获它。
  • DeserializeAsync 不会直接抛出,但底层的JsonReader 绝对会。您可以看到 JsonParsingException 本地方法在此处定义:github.com/neuecc/Utf8Json/blob/master/src/Utf8Json/… 并在整个 JsonReader 类中被多次引用。
  • 啊,现在说得通了。我在看DeserializeAsync 所以错过了它。感谢您的链接。欣赏它。
猜你喜欢
  • 2010-10-08
  • 2010-11-08
  • 2014-11-30
  • 1970-01-01
  • 2013-05-02
  • 2014-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多