Newtonsoft Serialization抛出InvalidCastException

时间:2018-04-09 20:03:13

标签: c# json serialization

我们正在努力弄清楚如何解决这个InvalidCastException

enter image description here

"ExceptionType": "System.InvalidCastException",
"StackTrace": "  at ...Objects.Patient.Equals(Object obj) in 
 at System.Collections.Generic.ObjectEqualityComparer`1.Equals(T x, T y)\r\n   at System.Collections.Generic.List`1.Contains(T item)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference

事实上,我们在过去发现了类似的帖子,这个帖子也引发了同样的异常。为了重现它,我们将一个简单的WinForm

放入其中
private void buttonJsonSerializer_Click(object sender, EventArgs e)
{
    var fixture = new Fixture
    {
        Name = "Fixture Name",
        participant = new Participant { Name = "Participant Name"}
    };

    fixture.participant = new Participant();            

    var writer = new StringWriter(new StringBuilder());
    var serializer = new JsonSerializer();
    serializer.Converters.Add(new StringEnumConverter());
    serializer.Serialize(writer, fixture);
    string output = writer.ToString();

}

public class Fixture
{
    public string Name { get; set; }            
    public Participant participant { get; set; }

    public override bool Equals(object obj)
    {
        var fixture = (Fixture)obj; // *** THROWS CAST EXCEPTION ***

        return fixture.Name == Name;
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}

public class Participant
{
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        var participant = (Participant)obj;

        return participant.Name == Name;
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}

提出的一个问题是:它与Newtonsoft库有什么关系吗?

而且,使用var fixture = obj as Fixture并不是我们在这种情况下要做的事情,因为它只会返回null。

1 个答案:

答案 0 :(得分:2)

您不能假设Fixture::Equals的论点永远是Fixture

public override bool Equals(object obj)
{
    if (obj is Fixture fixture)
    {
        return fixture.Name == Name;
    }

    return false;
}

而且,您需要对Participant::Equals执行相同操作:

public override bool Equals(object obj)
{
    if (obj is Participant participant)
    {
        return participant.Name == Name;
    }

    return false;
}
  

提出的一个问题是:它与Newtonsoft库有什么关系吗?

它确实:

  

在UserQuery.Fixture.Equals(Object obj)at   System.Collections.Generic.ObjectEqualityComparer 1.Equals(T x, T y)
at System.Collections.Generic.List
1.包含(T项)at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter   writer,Object value,JsonProperty属性,JsonContract契约,   JsonContainerContract containerContract,JsonProperty   containerProperty)at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter   writer,Object value,JsonContainerContract contract,JsonProperty   成员,JsonProperty财产,JsonContract& memberContract,Object&   memberValue)at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter   writer,Object value,JsonObjectContract契约,JsonProperty   成员,JsonContainerContract collectionContract,JsonProperty   containerProperty)at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter   jsonWriter,Object value,Type objectType)at   Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter   jsonWriter,Object value,Type objectType)at   Newtonsoft.Json.JsonSerializer.Serialize(TextWriter textWriter,Object   在UserQuery.Main()的at)   LINQPad.ExecutionModel.ClrQueryRunner.Run()at   LINQPad.ExecutionModel.Server.RunQuery(QueryRunner runner)at   LINQPad.ExecutionModel.Server.StartQuery(QueryRunner runner)at   LINQPad.ExecutionModel.Server<> c__DisplayClass152_0.b__0()   在LINQPad.ExecutionModel.Server.SingleThreadExecuter.Work()at   System.Threading.ExecutionContext.RunInternal(执行上下文   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.ExecutionContext.Run(执行上下文   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.ExecutionContext.Run(执行上下文   executionContext,ContextCallback回调,对象状态)at   System.Threading.ThreadHelper.ThreadStart()

JsonSerializerInternalWriter::CheckForCircularReference正在调用Equals进行循环引用。