Сериализовать одно-много отношений в Json.net

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

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

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

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

Я получаю сериализацию Исключение "Явный цикл ссылок, обнаруженный для типа", когда я пытаюсь сериализовать объект компании.

Спасибо.

Ответ 1

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

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

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

PreserveReferencesHandling = PreserveReferencesHandling.Objects;

Итак, пример будет таким:

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

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

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

Ответ 2

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

Вы можете:

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

Ответ 3

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

Мы используем подход Database First DbContext. Для наших нужд мы можем разрешить его с помощью атрибута [JsonIgnore]. Фокус в том, что, поскольку изменения в автоматически создаваемых классах сущностей перезаписываются при обновлении из базы данных, с помощью Database First вы можете добавлять атрибуты, используя подход класса "metadata buddy", приведенный в fooobar.com/questions/25201/....

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

Объект 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; }
}

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

Ответ 4

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

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

Microsoft: Обработка ссылок Loop в веб-интерфейсе