Сериализуйте отношения один ко многим в Json.net - PullRequest
19 голосов
/ 24 апреля 2011

Сначала я использую код Entity Framework для доступа к данным, и у меня есть класс Company, в котором есть коллекция Employees.Класс Employee также имеет свойство Company.

Я хотел бы иметь возможность сериализовать Company и включить в сериализацию список сотрудников.

Вот компания:

public class Company
{
public long Id { get; set; }
public string Name { get; set; }
public DateTime? Established { get; set; }

public virtual IList<Employee> Employees { get; set; }

public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}

Вот Сотрудник

public class Employee
{
public long Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }

public virtual Company Company { get; set; }

public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}

Я получаю исключение сериализации "Обнаружен цикл самоссылки для типа" при попытке сериализации объекта Company.

Спасибо.

Ответы [ 5 ]

14 голосов
/ 10 апреля 2012

Я думаю, они исправили это в последней версии.

Ознакомьтесь с справочными документами в разделе " Сериализация и десериализация JSON -> Сериализация и сохранение ссылок на объекты".

Установите этот параметр при инициализации сериализатора JSON.Net:

PreserveReferencesHandling = PreserveReferencesHandling.Objects;

. Примером может быть такой:

var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };

string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings);

Я подтвердил, чтоработает с моим первым решением кода и круговой ссылкой в ​​свойствах навигации.Если вы посмотрите на полученный JSON, он должен везде иметь свойства $ id и $ ref.

6 голосов
/ 24 апреля 2011

Обновленный ответ

Вы можете либо:

  • перенастроить json.net на игнорирование петли самореференции
  • используйте атрибут [JsonIgnore]
  • используйте пользовательский конвертер, который удаляет Навигация у ребенка
  • или вы можете использовать объекты передачи данных
5 голосов
/ 07 февраля 2014

Если вы получаете эту ошибку с помощью WebApi, вы можете поместить следующее в WebApiConfig.cs, чтобы json.net игнорировал круговые ссылки

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

Microsoft: обработка циклических ссылок в Web API

5 голосов
/ 25 апреля 2012

В случае, если это кому-нибудь поможет, я решил документировать, как мы решили эту же ошибку для наших целей при использовании Entity Framework 4.3.1 и JSON.Net 4.5.3.

Мы используем подход Database First DbContext.Для наших нужд мы могли бы разрешить это, используя атрибут [JsonIgnore].Хитрость заключается в том, что поскольку изменения в автоматически сгенерированных классах сущностей перезаписываются при обновлении из базы данных, с помощью Database First вы можете добавлять атрибуты, используя подход «класс метаданных друзей», приведенный в в этом сообщении StackOverflow .

Ниже приведен фрагмент кода.У нас был объект «Запрос» (class Query), который имел отношения к объектам «Компания» и «Пользователь».В новом файле класса мы объявляем частичный класс с атрибутом [MetadataType], а затем в указанном классе QueryMetadata мы аннотируем членов, которые хотим игнорировать, а именно членов public virtual, к которым EF4.x добавляетвыразить отношения (иначе известные свойства навигации).

Сущность Query также имеет поля внешнего ключа (в нашем случае FK_User и FK_Company).Этим полям не требуется атрибут [JsonIgnore] - их можно сериализовать с использованием значений их внешних ключей.

[MetadataType(typeof(QueryMetadata))]
public partial class Query
{
}


public class QueryMetadata
{
    [JsonIgnore]
    public virtual Company company { get; set; }
    [JsonIgnore]
    public virtual User user { get; set; }
}

Однако, если бы нам действительно пришлось также сериализовать связанные объекты Company или User, мы бы нажаликирпичная стена!Подход, предложенный Джоном Бубриски здесь , не будет работать для нас, поскольку мы хотим полагаться на отслеживание изменений Entity Framework.

1 голос
/ 28 мая 2018

Если вы используете WebAPI EntityFrameworkCore 2.0, это решение не работает, вам нужно установить его на Startup.cs-> ConfigureServices:

.AddJsonOptions(options => {
                    var settings = options.SerializerSettings;
                    settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                });
...