Сериализация Newtonsoft выдает исключение InvalidCastException

Мы пытаемся решить, как решить эту проблему с InvalidCastException.

Сериализация Newtonsoft выдает исключение InvalidCastException

"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.

Просто исправьте свою реализацию Equals. Он должен проверить, является ли obj пациентом, а если нет - должен вернуть false. Как ваша реализация неверна.

Evk 09.04.2018 22:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
305
1

Ответы 1

Вы не можете просто предположить, что аргумент 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;
}

One of questions that came up was: does it have anything to do with the Newtonsoft library ?

Оно делает:

at UserQuery.Fixture.Equals(Object obj) at System.Collections.Generic.ObjectEqualityComparer1.Equals(T x, T y)
at System.Collections.Generic.List
1.Contains(T item) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, 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 value) at 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() at LINQPad.ExecutionModel.Server.SingleThreadExecuter.Work() at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

JsonSerializerInternalWriter::CheckForCircularReference обращается к Equals для справки.

На самом деле это связано с проверкой циклических ссылок. Для подтверждения см. При проверке циклических ссылок следует использовать равенство ссылок на объект # 401, где Джеймс Ньютон-Кинг подтверждает, что проверка циклических ссылок через object.Equals() является предполагаемым поведением: Я предпочитаю текущее поведение, которое позволяет разработчикам настраивать логику, переопределяя Equals.

dbc 10.04.2018 01:39

Другие вопросы по теме