Ошибка JSON.NET Обнаружена собственная ссылка на тип
Я попытался сериализовать класс POCO, который был автоматически сгенерирован из Entity Data Model .edmx, и когда я использовал
JsonConvert.SerializeObject
Я получил следующую ошибку:
Произошла ошибка Самостоятельная ссылка на тип System.data.entity.
Как мне решить эту проблему?
28 ответов
Это было лучшее решение https://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. Уровень ссылок не может контролироваться, если существует глубокая цепочка ссылок.
Если вы хотите использовать это исправление в не ASPI-проекте ASP.NET, вы можете добавить приведенную выше строку в 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: игнорировать и сохранять ссылочные атрибуты
Это исправление - атрибуты decorate в классе модели для управления поведением сериализации на уровне модели или свойства. Чтобы игнорировать свойство:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
[IgnoreDataMember]
public virtual ICollection<Product> Products { get; set; }
}
JsonIgnore - для JSON.NET, а IgnoreDataMember - для XmlDCSerializer. Чтобы сохранить ссылку:
// Fix 3
[JsonObject(IsReference = true)]
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
// Fix 3
//[JsonIgnore]
//[IgnoreDataMember]
public virtual ICollection<Product> Products { get; set; }
}
[DataContract(IsReference = true)]
public class Product
{
[Key]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public virtual Category Category { get; set; }
}
JsonObject(IsReference = true)]
для JSON.NET и [DataContract(IsReference = true)]
для XmlDCSerializer. Обратите внимание, что: после применения DataContract
на уроке, вам нужно добавить DataMember
к свойствам, которые вы хотите сериализовать.
Атрибуты могут быть применены как к сериализатору json, так и к сериализатору xml и предоставляют больше элементов управления классу модели
Использовать JsonSerializerSettings
ReferenceLoopHandling.Error
(по умолчанию) выдаст ошибку, если будет обнаружен ссылочный цикл. Вот почему вы получаете исключение.ReferenceLoopHandling.Serialize
полезно, если объекты вложены, но не бесконечно.ReferenceLoopHandling.Ignore
не будет сериализовать объект, если он сам по себе является дочерним объектом.
Пример:
JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented,
new JsonSerializerSettings {
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
});
Если вам нужно сериализовать объект, который вложен неопределенно долго, вы можете использовать PreserveObjectReferences, чтобы избежать StackruException.
Пример:
JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented,
new JsonSerializerSettings {
PreserveReferencesHandling = PreserveReferencesHandling.Objects
});
Выберите, что имеет смысл для объекта, который вы сериализуете.
Исправление состоит в том, чтобы игнорировать ссылки на циклы и не сериализовать их. Это поведение указано в JsonSerializerSettings
,
не замужем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]
атрибут виртуального свойства в классе, например:
public string Name { get; set; }
public string Description { get; set; }
public Nullable<int> 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<char>.Shared));
});
}
Если вы используете.NET Core 2.0, обновите раздел ConfigureServices в Startup.cs
https://docs.microsoft.com/en-us/ef/core/querying/related-data
public void ConfigureServices(IServiceCollection services)
{
...
services.AddMvc()
.AddJsonOptions(
options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
...
}
Чтобы сериализовать нас в NEWTONSOFTJSON, когда у вас есть проблема с циклом, в моем случае мне не нужно было изменять global.asax или apiconfig. Я просто использую JsonSerializesSettings, игнорируя обработку циклов.
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var lst = db.shCards.Where(m => m.CardID == id).ToList();
string json = JsonConvert.SerializeObject(lst, jss);
Мы можем добавить эти две строки в конструктор класса DbContext, чтобы отключить цикл Self-ссылки, например
public TestContext()
: base("name=TestContext")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
Вы также можете применить атрибут к свойству. [JsonProperty( ReferenceLoopHandling = ... )]
атрибут хорошо подходит для этого.
Например:
/// <summary>
/// Represents the exception information of an event
/// </summary>
public class ExceptionInfo
{
// ...code omitted for brevity...
/// <summary>
/// An inner (nested) error.
/// </summary>
[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<MvcOptions>(options =>
{
options.OutputFormatters.RemoveTypesOf<JsonOutputFormatter>();
var jsonOutputFormatter = new JsonOutputFormatter();
jsonOutputFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
options.OutputFormatters.Insert(0, jsonOutputFormatter);
});
}
Просто обновите services.AddControllers() в файле Startup.cs
services.AddControllers()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
Код C#:
var jsonSerializerSettings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
};
var jsonString = JsonConvert.SerializeObject(object2Serialize, jsonSerializerSettings);
var filePath = @"E:\json.json";
File.WriteAllText(filePath, jsonString);
У меня было это исключение, и мое рабочее решение легко и просто,
Игнорируйте свойство Referenced, добавив в него атрибут JsonIgnore:
[JsonIgnore]
public MyClass currentClass { get; set; }
Сбросьте свойство при его десериализации:
Source = JsonConvert.DeserializeObject<MyObject>(JsonTxt);
foreach (var item in Source)
{
Source.MyClass = item;
}
используя Newtonsoft.Json;
В .Net 5.x обновите метод ConfigureServices в startup.cs с помощью приведенного ниже кода.
public void ConfigureServices(IServiceCollection services)
{
----------------
----------------
services.AddMvc().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
});
------------------
}
По умолчанию сериализация (System.Text.Json.Serialization) не поддерживает объекты с циклами и не сохраняет повторяющиеся ссылки. Используйте Preserve, чтобы включить сохранение уникальных ссылок на объект при сериализации и использование метаданных для чтения сохраненных ссылок при десериализации. Ссылка MSDN
Команда:
Это работает с ASP.NET Core; Сложность заключается в том, как установить "игнорирование". В зависимости от того, как вы настраиваете ваше приложение, оно может быть довольно сложным. Вот что сработало для меня.
Это может быть размещено в вашем общедоступном разделе ConfigureServices(IServiceCollection services).
services.AddMvc().AddJsonOptions(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
Люди уже говорили о том, что [JsonIgnore] будет добавлено к виртуальному свойству в классе, например:
[JsonIgnore]
public virtual Project Project { get; set; }
Я также поделюсь другой опцией, [JsonProperty(NullValueHandling = NullValueHandling.Ignore)], которая пропускает свойство из сериализации, только если оно равно нулю.
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public virtual Project Project { get; set; }
Используйте это в WebApiConfig.cs
учебный класс:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
Для меня я должен был пойти другим путем. Вместо того, чтобы пытаться исправить сериализатор JSON.Net, мне пришлось пойти после "Ленивой загрузки" в моем тексте данных.
Я только что добавил это в свой базовый репозиторий:
context.Configuration.ProxyCreationEnabled = false;
Объект context является параметром конструктора, который я использую в своем базовом репозитории, потому что я использую внедрение зависимостей. Вместо этого вы можете изменить свойство ProxyCreationEnabled, где бы вы ни создавали свой текстовый текст.
http://techie-tid-bits.blogspot.com/2015/09/jsonnet-serializer-and-error-self.html
Для.NET Core 3.0 обновите класс Startup.cs, как показано ниже.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllers()
.AddNewtonsoftJson(
options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
...
}
См.: https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-0-preview-5/
Также убедитесь, что в вашем методе используются await и async. Вы можете получить эту ошибку, если ваш объект не сериализован должным образом.
Я унаследовал приложение базы данных, которое обслуживает модель данных на веб-странице. Сериализация по умолчанию будет пытаться пройти по всему дереву модели, и большинство ответов здесь являются хорошим началом того, как этого избежать.
Один из вариантов, который не изучался, - это использование интерфейсов для помощи. Я украду из предыдущего примера:
public partial class CompanyUser
{
public int Id { get; set; }
public int CompanyId { get; set; }
public int UserId { get; set; }
public virtual Company Company { get; set; }
public virtual User User { get; set; }
}
public interface IgnoreUser
{
[JsonIgnore]
User User { get; set; }
}
public interface IgnoreCompany
{
[JsonIgnore]
User User { get; set; }
}
public partial class CompanyUser : IgnoreUser, IgnoreCompany
{
}
В приведенном выше решении никакие настройки Json не пострадают. Установка LazyLoadingEnabled и / или ProxyCreationEnabled на false влияет на все ваше внутреннее кодирование и предотвращает некоторые из истинных преимуществ инструмента ORM. В зависимости от вашего приложения настройки LazyLoading/ProxyCreation могут предотвратить загрузку свойств навигации без их ручной загрузки.
Вот гораздо лучшее решение для предотвращения сериализации свойств навигации, использующее стандартные функции json: Как я могу заставить сериализатор JSON игнорировать свойства навигации?
Моя проблема решена с помощью пользовательской конфигурации JsonSerializerSettings:
services.AddMvc(
// ...
).AddJsonOptions(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Serialize;
opt.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.Objects;
});
Если бы эта проблема исходила от одного из сторонних пакетов nuget. Не было возможности изменить конфигурацию или сериализацию. Установка пакета Newtonsoft.Json в моем потребительском проекте решила проблему.
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
Просто место Configuration.ProxyCreationEnabled = false;
внутри файла контекста; это решит проблему.
public demEntities()
: base("name=demEntities")
{
Configuration.ProxyCreationEnabled = false;
}
Очень похоже на другие здесь. Решено с помощью настроек сериализатора. Однако моя возникла из-за того, что я использовал сторону FromObject, поскольку мне нужен был JObject для работы.
Это означает, что вам просто нужно создать сериализатор по умолчанию и применить к нему настройки. Простое исправление становится этим
var deserializerSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
};
var serializer = JsonSerializer.CreateDefault(deserializerSettings);
JObject jsonObject = (JObject)JToken.FromObject(mySelfRefernceObject, serializer);
Я столкнулся с той же проблемой, и я попытался использовать JsonSetting, чтобы игнорировать ошибку самореференции, это своего рода работа, пока я не получил класс, который очень глубоко ссылается на себя, и мой процесс dot-net зависает от значения записи Json.
Моя проблема
public partial class Company : BaseModel
{
public Company()
{
CompanyUsers = new HashSet<CompanyUser>();
}
public string Name { get; set; }
public virtual ICollection<CompanyUser> CompanyUsers { get; set; }
}
public partial class CompanyUser
{
public int Id { get; set; }
public int CompanyId { get; set; }
public int UserId { get; set; }
public virtual Company Company { get; set; }
public virtual User User { get; set; }
}
public partial class User : BaseModel
{
public User()
{
CompanyUsers = new HashSet<CompanyUser>();
}
public string DisplayName { get; set; }
public virtual ICollection<CompanyUser> CompanyUsers { get; set; }
}
Вы можете увидеть проблему в классе User, который ссылается на класс CompanyUser, который ссылается на себя.
Теперь я вызываю метод GetAll, который включает все реляционные свойства.
cs.GetAll("CompanyUsers", "CompanyUsers.User");
На этом этапе мой процесс DotNetCore зависает при выполнении JsonResult, записывает значение... и никогда не приходит. В моем Startup.cs я уже установил JsonOption. По какой-то причине EFCore включает вложенное свойство, которое я не прошу предоставить Ef.
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
ожидаемое поведение должно быть таким
Привет, EfCore, не могли бы вы также включить данные "CompanyUsers" в мой класс компании, чтобы я мог легко получить к ним доступ.
тогда
Привет, EfCore, не могли бы вы также включить данные "CompanyUsers.User", чтобы я мог легко получить доступ к таким данным, как эта Company.CompanyUsers.First().User.DisplayName
на этом этапе я должен получить только этот "Company.CompanyUsers.First(). User.DisplayName", и он не должен давать мне Company.CompanyUsers.First(). User.CompanyUsers, которая вызывает проблему с самообращением; Технически это не должно давать мне User.CompanyUsers, поскольку CompanyUsers - это свойство навигации. Но EfCore очень обрадовался и предоставил мне User.CompanyUsers.
Итак, я решил написать метод расширения для свойства, которое будет исключено из объекта (на самом деле он не исключает, просто установив для свойства значение null). Мало того, что он также будет работать со свойствами массива. ниже приведен код, который я также собираюсь экспортировать для других пользователей (не уверен, что это кому-то поможет). Причина проста, потому что мне лень писать .Select(n => new { n.p1, n.p2}); Я просто не хочу писать оператор select, чтобы исключить только 1 свойство!
Это не лучший код (я обновлю на каком-то этапе), поскольку я написал в спешке, и хотя это может помочь кому-то, кто хочет исключить (установить null) также в объект с массивами.
public static class PropertyExtensions
{
public static void Exclude<T>(this T obj, Expression<Func<T, object>> expression)
{
var visitor = new PropertyVisitor<T>();
visitor.Visit(expression.Body);
visitor.Path.Reverse();
List<MemberInfo> paths = visitor.Path;
Action<List<MemberInfo>, object> act = null;
int recursiveLevel = 0;
act = (List<MemberInfo> vPath, object vObj) =>
{
// set last propert to null thats what we want to avoid the self-referencing error.
if (recursiveLevel == vPath.Count - 1)
{
if (vObj == null) throw new ArgumentNullException("Object cannot be null");
vObj.GetType().GetMethod($"set_{vPath.ElementAt(recursiveLevel).Name}").Invoke(vObj, new object[] { null });
return;
}
var pi = vObj.GetType().GetProperty(vPath.ElementAt(recursiveLevel).Name);
if (pi == null) return;
var pv = pi.GetValue(vObj, null);
if (pi.PropertyType.IsArray || pi.PropertyType.Name.Contains("HashSet`1") || pi.PropertyType.Name.Contains("ICollection`1"))
{
var ele = (IEnumerator)pv.GetType().GetMethod("GetEnumerator").Invoke(pv, null);
while (ele.MoveNext())
{
recursiveLevel++;
var arrItem = ele.Current;
act(vPath, arrItem);
recursiveLevel--;
}
if (recursiveLevel != 0) recursiveLevel--;
return;
}
else
{
recursiveLevel++;
act(vPath, pv);
}
if (recursiveLevel != 0) recursiveLevel--;
};
// check if the root level propert is array
if (obj.GetType().IsArray)
{
var ele = (IEnumerator)obj.GetType().GetMethod("GetEnumerator").Invoke(obj, null);
while (ele.MoveNext())
{
recursiveLevel = 0;
var arrItem = ele.Current;
act(paths, arrItem);
}
}
else
{
recursiveLevel = 0;
act(paths, obj);
}
}
public static T Explode<T>(this T[] obj)
{
return obj.FirstOrDefault();
}
public static T Explode<T>(this ICollection<T> obj)
{
return obj.FirstOrDefault();
}
}
Приведенный выше класс расширения даст вам возможность установить для свойства значение null, чтобы избежать цикла самореференции даже с массивами.
Построитель выражений
internal class PropertyVisitor<T> : ExpressionVisitor
{
public readonly List<MemberInfo> Path = new List<MemberInfo>();
public Expression Modify(Expression expression)
{
return Visit(expression);
}
protected override Expression VisitMember(MemberExpression node)
{
if (!(node.Member is PropertyInfo))
{
throw new ArgumentException("The path can only contain properties", nameof(node));
}
Path.Add(node.Member);
return base.VisitMember(node);
}
}
Использование:
Модельные классы
public class Person
{
public string Name { get; set; }
public Address AddressDetail { get; set; }
}
public class Address
{
public string Street { get; set; }
public Country CountryDetail { get; set; }
public Country[] CountryDetail2 { get; set; }
}
public class Country
{
public string CountryName { get; set; }
public Person[] CountryDetail { get; set; }
}
Фиктивные данные
var p = new Person
{
Name = "Adeel Rizvi",
AddressDetail = new Address
{
Street = "Sydney",
CountryDetail = new Country
{
CountryName = "AU"
}
}
};
var p1 = new Person
{
Name = "Adeel Rizvi",
AddressDetail = new Address
{
Street = "Sydney",
CountryDetail2 = new Country[]
{
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A1" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A2" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A3" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A4" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A5" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A6" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A7" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A8" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A9" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A1" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A2" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A3" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A4" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A5" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A6" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A7" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A8" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A9" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
}
}
};
Кейсы:
Случай 1. Исключить только свойство без массива
p.Exclude(n => n.AddressDetail.CountryDetail.CountryName);
Случай 2: исключить свойство с 1 массивом
p1.Exclude(n => n.AddressDetail.CountryDetail2.Explode().CountryName);
Случай 3: исключить свойство с 2 вложенными массивами
p1.Exclude(n => n.AddressDetail.CountryDetail2.Explode().CountryDetail.Explode().Name);
Случай 4. Запрос EF GetAll с включениями
var query = cs.GetAll("CompanyUsers", "CompanyUsers.User").ToArray();
query.Exclude(n => n.Explode().CompanyUsers.Explode().User.CompanyUsers);
return query;
Вы заметили, что метод Explode() также является методом расширения только для нашего построителя выражений, чтобы получить свойство из свойства массива. Когда есть свойство массива, используйте .Explode().YourPropertyToExclude или.Explode().Property1.MyArrayProperty.Explode().MyStupidProperty. Приведенный выше код помогает мне избежать ссылок на себя настолько глубоко, насколько я хочу. Теперь я могу использовать GetAll и исключить свойство, которое мне не нужно!
Спасибо, что прочитали этот большой пост!
Для того, чтобы не зацикливание это работало для меняReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Я решил все это здесь - сериализация дочерних платформ Entity Framework с помощью.Net Core 2 WebAPI https://gist.github.com/Kaidanov/f9ad0d79238494432f32b8407942c606
Буду признателен за любые замечания. Может быть, кто-то может использовать это когда-нибудь
Мне понравилось решение, которое делает это из Application_Start()
как в ответе здесь
По-видимому, я не смог получить доступ к объектам json в JavaScript, используя конфигурацию в моей функции, как в ответе DalSoft, поскольку возвращаемый объект имел "\n \r" по всему (key, val) объекта.
В любом случае, все, что работает, отлично (потому что разные подходы работают в разных сценариях на основе комментариев и заданных вопросов), хотя стандартный способ сделать это предпочтительнее с хорошей документацией, поддерживающей подход.