将 AutoMapperMappingException 转换为 JSON

Convert AutoMapperMappingException To JSON

在尝试对某些代码进行故障排除时,我查看了捕获任何未处理异常的日志。

在我的日志函数中,我有以下代码行:

data = JsonConvert.DeserializeObject(exception)

部分数据的值读取,\"Message\":null。当我调试并查看异常时,异常的 Message 属性 有一个值(准确描述了问题)。如果我尝试使用上面的行将不同的异常转换为 JSON,我会在结果 JSON.

中看到消息 属性 的值

我错过了什么?

这看起来像是 AutoMapperMappingException. Json.NET supports ISerializable, and the base class System.Exception implements this interface. As can be seen from the reference source, the base class version of GetObjectData 中的错误,只是添加了 基本字段值 而不是 属性 值 到序列化流:

        info.AddValue("Message", _message, typeof(String));

Exception 的任何子class 包含超出基础 class 的额外数据必须需要覆盖 GetObjectData 并序列化它自己的数据。例如,这里是 ArgumentOutOfRangeException:

的实现
    public override void GetObjectData(SerializationInfo info, StreamingContext context) {
        if (info==null) {
            throw new ArgumentNullException("info");
        }
        Contract.EndContractBlock();
        base.GetObjectData(info, context);
        info.AddValue("ActualValue", m_actualValue, typeof(Object));
    }

现在,从其source code, AutoMapperMappingException overrides Exception.Message输出额外的数据。事实上,基本消息可能为空:

    public override string Message
    {
        get
        {
            string message = null;
            var newLine = Environment.NewLine;
            if (Context != null)
            {
                message = _message + newLine + newLine + "Mapping types:";
                message += newLine + string.Format("{0} -> {1}", Context.SourceType.Name, Context.DestinationType.Name);
                message += newLine + string.Format("{0} -> {1}", Context.SourceType.FullName, Context.DestinationType.FullName);

                var destPath = GetDestPath(Context);
                message += newLine + newLine + "Destination path:" + newLine + destPath;

                message += newLine + newLine + "Source value:" + newLine + (Context.SourceValue ?? "(null)");

                return message;
            }
            if (_message != null)
            {
                message = _message;
            }

            message = (message == null ? null : message + newLine) + base.Message;

            return message;
        }
    }

不会,但是会覆盖 GetObjectData(),这是错误。

要解决此问题,您可以编写自己的自定义 JsonConverter 并序列化消息 属性 而不是基本字段:

public class ExceptionConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(AutoMapperMappingException).IsAssignableFrom(objectType);
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var exception = (Exception)value;
        var obj = JObject.FromObject(exception);
        obj["Message"] = exception.Message;
        obj.WriteTo(writer);
    }
}

这至少可以确保消息存在。但是,ResolutionContext property of AutoMapperMappingException 仍然不会被序列化,因此产生的反序列化异常将丢失一些数据。

或者,您可以尝试使用 Json.NET 的默认序列化序列化和反序列化 ResolutionContext,并将其作为 属性 添加到转换器中。不确定它是否会起作用,但它可能会起作用。或者尝试 report an issue.

(或者,只记录异常的 ToString() 输出,这通常就足够了。)