【问题标题】:Json.net fails when trying to deserialize a class that inherits from Exception尝试反序列化从 Exception 继承的类时,Json.net 失败
【发布时间】:2012-12-20 14:16:48
【问题描述】:

我有一个继承自 Exception 的类 SearchError,当我尝试从有效的 json 反序列化它时,我得到以下异常:

ISerializable 类型“SearchError”没有有效的构造函数。要正确实现 ISerializable,应该存在采用 SerializationInfo 和 StreamingContext 参数的构造函数。路径 '',第 1 行,位置 81。

我尝试实现建议的缺失构造函数,但没有帮助。

这是实现建议的构造函数后的类:

public class APIError : Exception
{
    [JsonProperty("error")]
    public string Error { get; set; }

    [JsonProperty("@http_status_code")]
    public int HttpStatusCode { get; set; }

    [JsonProperty("warnings")]
    public List<string> Warnings { get; set; }

    public APIError(string error, int httpStatusCode, List<string> warnings) : base(error)
    {
        this.Error = error;
        this.HttpStatusCode = httpStatusCode;
        this.Warnings = warnings;
    }

    public APIError(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
        : base(info, context)
    {
        Error = (string)info.GetValue("error", typeof(string));
        HttpStatusCode = (int)info.GetValue("@http_status_code", typeof(int));
        Warnings = (List<string>)info.GetValue("warnings", typeof(List<string>));
    }
}

现在我得到以下异常(也在 json.net 代码中):

找不到成员“ClassName”。

我也尝试实现与this related question 中相同的解决方案,也得到了与上述相同的错误。

【问题讨论】:

标签: c# json json.net


【解决方案1】:

这里已经回答了这个问题:https://stackoverflow.com/a/3423037/504836

添加一个新的构造函数

public Error(SerializationInfo info, StreamingContext context){}

解决了我的问题。

这里完整的代码:

[Serializable]
public class Error : Exception
{

    public string ErrorMessage { get; set; }

    public Error(SerializationInfo info, StreamingContext context) {
        if (info != null)
            this.ErrorMessage = info.GetString("ErrorMessage");
    }
    public override void GetObjectData(SerializationInfo info,StreamingContext context)
    {
        base.GetObjectData(info, context);

        if (info != null)
            info.AddValue("ErrorMessage", this.ErrorMessage);
    }
}

【讨论】:

  • 这个答案是没用的,因为你不能总是把一个成员添加到你不拥有的类中。例如,我在尝试序列化实体框架抛出的 DbUpdateConcurrencyException 时遇到此错误。我无法控制该类或其成员或抛出哪种实例。
  • @Lukasz Lysik 是正确的,答案需要改进,但实际上最好的改进是简化。我已经通过单步执行代码并保存整个对象及其属性来确认,必须在 GetObjectData 中的唯一语句是第一个语句 base.GetObjectData(info, context);我已经确认每个属性都会被填充,包括在 .NET 2.0 中受保护的 HRESULT。构造函数也是如此。
  • 这有什么特别的原因吗?它是 JSON.NET 中的错误吗?添加到数百个自定义异常中是一件可怕的事情。
【解决方案2】:

正如错误所说,您缺少序列化构造函数:

public class SearchError : Exception
{
    public SearchError(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context)
    {

    }
}

【讨论】:

  • 我已经尝试过您之前已经尝试过的建议,现在我遇到了一些其他异常(见上文)。
  • ": base(info, context)" 抛出异常“未找到成员 'ClassName'。”
  • @joelnet:这是您的代码的问题,而不是答案。参见 MSDN 链接,例如:msdn.microsoft.com/en-us/library/…
  • @joelnet:答案中的示例有效。我们有几十个以这种方式配置的类。此外,MSDN 链接包含一个工作示例。如果您的代码有特定问题,那么您应该创建一个新问题,而不是对答案投反对票,然后在 cmets 中寻求帮助。
  • 序列化构造函数并不总是丢失,它可以受到保护,例如在实体框架中使用 DbUpdateConcurrencyException。另外,这种答案也不好,因为如果您不拥有该课程,则无法应用。这似乎更像是 JSON.NET 中的一个错误,因为它无法找到受保护的构造函数。
猜你喜欢
  • 1970-01-01
  • 2014-01-06
  • 2012-06-20
  • 1970-01-01
  • 2012-09-05
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多