Ошибка JSON.NET Локальный цикл привязки для типа

Я попытался сериализовать class POCO, который был автоматически сгенерирован из Entity Data Model .edmx, и когда я использовал

JsonConvert.SerializeObject 

Я получил следующую ошибку:

Ошибка Обнаружен цикл саморегуляции, для которого зарегистрирован тип System.data.entity.

Как решить эту проблему?

Это было лучшее решение http://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

Исправление 1: игнорирование круговой ссылки по всему миру

(Я выбрал / попробовал это, как и многие другие)

Серийный анализатор json.net имеет возможность игнорировать циклические ссылки. Поместите следующий код в файл WebApiConfig.cs :

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

Простое исправление заставит сериализатор игнорировать ссылку, которая вызовет цикл. Однако он имеет ограничения:

Данные теряют справочную информацию цикла. Исправление применяется только к JSON.net. Уровень ссылок не может контролироваться, если существует глубокая ссылочная цепочка

Если вы хотите использовать это исправление в проекте ASP.NET, отличном от api, вы можете добавить Global.asax.cs выше строку в Global.asax.cs , но сначала добавьте:

 var config = GlobalConfiguration.Configuration; 

Если вы хотите использовать это в проекте .Net Core , вы можете изменить Startup.cs следующим образом:

  var mvc = services.AddMvc(options => { ... }) .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); 

Исправление 2: Сохранение круговой ссылки по всему миру

Это второе исправление похоже на первое. Просто измените код на:

 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize; config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; 

Форма данных будет изменена после применения этой настройки.

 [ { "$id":"1", "Category":{ "$id":"2", "Products":[ { "$id":"3", "Category":{ "$ref":"2" }, "Id":2, "Name":"Yogurt" }, { "$ref":"1" } ], "Id":1, "Name":"Diary" }, "Id":1, "Name":"Whole Milk" }, { "$ref":"3" } ] 

Идентификатор $ id и $ ref сохраняет все ссылки и делает уровень графа объекта плоским, но клиентский код должен знать изменение формы для использования данных, и это относится только к сериализатору JSON.NET.

Исправить 3: игнорировать и сохранять ссылочные атрибуты

Это исправление украшает атрибуты classа модели для управления сериализацией на уровне модели или свойства. Чтобы игнорировать свойство:

 1: public class Category 2: { 3: public int Id { get; set; } 4: public string Name { get; set; } 5: 6: [JsonIgnore] 7: [IgnoreDataMember] 8: public virtual ICollection Products { get; set; } 9: } 

JsonIgnore для JSON.NET и IgnoreDataMember для XmlDCSerializer. Чтобы сохранить ссылку:

 1: // Fix 3 2: [JsonObject(IsReference = true)] 3: public class Category 4: { 5: public int Id { get; set; } 6: public string Name { get; set; } 7: 8: // Fix 3 9: //[JsonIgnore] 10: //[IgnoreDataMember] 11: public virtual ICollection Products { get; set; } 12: } 13: 14: [DataContract(IsReference = true)] 15: public class Product 16: { 17: [Key] 18: public int Id { get; set; } 19: 20: [DataMember] 21: public string Name { get; set; } 22: 23: [DataMember] 24: public virtual Category Category { get; set; } 25: } 

JsonObject(IsReference = true)] для JSON.NET и [DataContract(IsReference = true)] для XmlDCSerializer. Обратите внимание: после применения DataContract для classа вам необходимо добавить DataMember в свойства, которые вы хотите сериализовать.

Атрибуты могут применяться как для сериализатора json, так и для xml и дают больше элементов управления classу модели.

Использовать JsonSerializerSettings

  • ReferenceLoopHandling.Error (по умолчанию) будет ошибкой, если встретится опорный цикл. Вот почему вы получаете исключение.
  • ReferenceLoopHandling.Serialize полезен, если объекты вложены, но не на неопределенный срок.
  • ReferenceLoopHandling.Ignore не будет сериализовать объект, если он является дочерним объектом.

Пример:

 JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize }); 

Если вам нужно сериализовать объект, который вложен неограниченно, вы можете использовать PreserveObjectReferences, чтобы избежать исключения StackOverflowException.

Пример:

 JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects }); 

Выберите то, что имеет смысл для объекта, который вы сериализуете.

Ссылка http://james.newtonking.com/json/help/

Исправление состоит в том, чтобы игнорировать ссылки на цикл, а не сериализовывать их. Это поведение указано в JsonSerializerSettings .

Single JsonConvert с перегрузкой:

 JsonConvert.SerializeObject(YourObject, Formatting.Indented, new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore } ); 

Глобальная настройка с кодом в Application_Start() в Global.asax.cs:

 JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented, ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore }; 

Ссылка: https://github.com/JamesNK/Newtonsoft.Json/issues/78

Самый простой способ сделать это – установить Json.NET из nuget и добавить [JsonIgnore] к виртуальному свойству в classе, например:

  public string Name { get; set; } public string Description { get; set; } public Nullable Project_ID { get; set; } [JsonIgnore] public virtual Project Project { get; set; } 

Хотя в эти дни я создаю модель с только теми свойствами, которые я хочу передать, поэтому она легче, не включает нежелательные коллекции, и я не теряю свои изменения, когда я перестраиваю сгенерированные файлы …

В .NET Core 1.0 вы можете установить это как глобальную настройку в файле Startup.cs:

 using System.Buffers; using Microsoft.AspNetCore.Mvc.Formatters; using Newtonsoft.Json; // beginning of Startup class public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.OutputFormatters.Clear(); options.OutputFormatters.Add(new JsonOutputFormatter(new JsonSerializerSettings(){ ReferenceLoopHandling = ReferenceLoopHandling.Ignore, }, ArrayPool.Shared)); }); } 

Мы можем добавить эти две строки в конструктор classа DbContext, чтобы отключить цикл саморегуляции, например

 public TestContext() : base("name=TestContext") { this.Configuration.LazyLoadingEnabled = false; this.Configuration.ProxyCreationEnabled = false; } 

Вы также можете применить атрибут к свойству. [JsonProperty( ReferenceLoopHandling = ... )] хорошо подходит для этого.

Например:

 ///  /// Represents the exception information of an event ///  public class ExceptionInfo { // ...code omitted for brevity... ///  /// An inner (nested) error. ///  [JsonProperty( ReferenceLoopHandling = ReferenceLoopHandling.Ignore, IsReference = true )] public ExceptionInfo Inner { get; set; } // ...code omitted for brevity... } 

Надеюсь, что это поможет, Jaans

Чтобы игнорировать ссылки на контуры и не сериализовать их глобально в MVC 6, используйте в startup.cs следующее:

  public void ConfigureServices(IServiceCollection services) { services.AddMvc().Configure(options => { options.OutputFormatters.RemoveTypesOf(); var jsonOutputFormatter = new JsonOutputFormatter(); jsonOutputFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; options.OutputFormatters.Insert(0, jsonOutputFormatter); }); } 

Используйте это в classе WebApiConfig.cs :

 var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove(config.Formatters.XmlFormatter); 

Для меня мне пришлось идти другим путем. Вместо того, чтобы пытаться исправить сериализатор JSON.Net, мне пришлось идти после Lazy Loading на моем datacontext.

Я просто добавил это в свой базовый repository:

 context.Configuration.ProxyCreationEnabled = false; 

Объект «context» – это параметр конструктора, который я использую в базовом репозитории, потому что я использую инъекцию зависимостей. Вы можете изменить свойство ProxyCreationEnabled везде, где вы создаете экземпляр вашего datacontext.

http://techie-tid-bits.blogspot.com/2015/09/jsonnet-serializer-and-error-self.html

Чтобы сериализовать usin NEWTONSOFTJSON, когда у вас проблема с циклом, в моем случае мне не нужно изменять global.asax или apiconfig. Я просто использую JsonSerializesSettings, игнорируя обработку Looping.

 JsonSerializerSettings jss = new JsonSerializerSettings(); jss.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; var lst = db.shCards.Where(m => m.CardID == id).ToList(); string json = JsonConvert.SerializeObject(lst, jss); 

У меня было это исключение, и мое рабочее решение было простым и простым,

Игнорируйте свойство Referenced, добавив к нему атрибут JsonIgnore:

 [JsonIgnore] public MyClass currentClass { get; set; } 

Сбросьте свойство при его десериализации:

 Source = JsonConvert.DeserializeObject(JsonTxt); foreach (var item in Source) { Source.MyClass = item; } 

используя Newtonsoft.Json;

Если вы используете .NET Core 2.0, обновите раздел ConfigureServices в Startup.cs

https://docs.microsoft.com/en-us/ef/core/querying/related-data#related-data-and-serialization

 public void ConfigureServices(IServiceCollection services) { ... services.AddMvc() .AddJsonOptions( options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore ); ... } 

Люди уже говорили о [JsonIgnore] для добавления в виртуальную собственность в classе, например:

 [JsonIgnore] public virtual Project Project { get; set; } 

Я также поделюсь еще одним вариантом, [JsonProperty (NullValueHandling = NullValueHandling.Ignore)], который опускает свойство из сериализации только в том случае, если он равен нулю.

 [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public virtual Project Project { get; set; } 

Просто установите Configuration.ProxyCreationEnabled = false; внутри контекстного файла; это решит проблему.

 public demEntities() : base("name=demEntities") { Configuration.ProxyCreationEnabled = false; } 

Для того, чтобы не зацикливаться, это сработало для меня –
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

Я решил все это здесь – сериализация дочерних элементов Entity Framework с .Net Core 2 WebAPI https://gist.github.com/Kaidanov/f9ad0d79238494432f32b8407942c606

Получу любые замечания. возможно, кто-то может когда-нибудь использовать его.

Мне понравилось решение, которое делает это из Application_Start() как в ответе здесь

По-видимому, я не мог получить доступ к json-объектам в JavaScript, используя конфигурацию в моей функции, как в ответе DalSoft, поскольку возвращаемый объект имел «\ n \ r» по всему (ключ, val) объекта.

Во всяком случае, все работает отлично (потому что разные подходы работают в разных сценариях, основываясь на комментариях и задаваемых вопросах), хотя стандартный способ сделать это предпочтительнее с хорошей документацией, поддерживающей этот подход.

  • Как десериализовать объект JObject для .NET
  • Можно ли выполнять бинарную сериализацию .NET в случае, если у вас нет исходного кода classа?
  • Json Сериализация Java, которая работает с GWT
  • Каковы различия между XmlSerializer и BinaryFormatter
  • Использовать имя classа в качестве корневого ключа для сериализации JSON Jackson
  • Как сериализовать словарь как часть его родительского объекта с помощью Json.Net
  • Jackson ObjectMapper - указать порядок сортировки свойств объекта
  • Сериализация с Qt
  • Json.NET: десериализация вложенных словарей
  • Задача не сериализуема: java.io.NotSerializableException при вызове функции закрытие только для classов не объектов
  • Есть ли у .NET 4 встроенный сериализатор / десериализатор JSON?
  • Давайте будем гением компьютера.