将AutoMapperMappingException转换为JSON

时间:2015-04-23 14:43:34

标签: json.net automapper

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

在我的日志功能中,我有以下代码行:

data = JsonConvert.DeserializeObject(exception)

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

我错过了什么?

1 个答案:

答案 0 :(得分:3)

这看起来像AutoMapperMappingException中的错误。 Json.NET支持ISerializable,基类System.Exception实现此接口。从reference source可以看出,GetObjectData的基类版本只是将基本字段值而不是属性值添加到序列化流中:

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

Exception的任何子类,包含基类之上和之外的其他数据,必须覆盖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 codeAutoMapperMappingException覆盖Exception.Message来输出其他数据。实际上,基本消息可能为null:

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

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

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

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