我一直在寻找如何避免返回没有属性lazyLoader的列表,我想继续使用lazyLoader,但是当我从控制器返回整个实体列表时,我不想返回属性
我正在使用 .NET 核心。
[
{
"lazyLoader": {},
"id": "id1"
"name": "name"
},
{
"lazyLoader": {},
"id": "id2",
"name": "name2"
}
]
我一直在寻找如何避免返回没有属性lazyLoader的列表,我想继续使用lazyLoader,但是当我从控制器返回整个实体列表时,我不想返回属性
我正在使用 .NET 核心。
[
{
"lazyLoader": {},
"id": "id1"
"name": "name"
},
{
"lazyLoader": {},
"id": "id2",
"name": "name2"
}
]
您可以选择仅检索其余数据的集合。这样,您的对象将根本没有 Navigation 属性。
db.YourCollection.Where(your condition)Select(x => new { id = x.id , name = x.name } );
在 Entity Framework 中,如果您的对象的一个或多个属性使用延迟加载,请使用 GetType().Name 检查其运行时类型名称。例如,对于Car类的对象,您会注意到运行时类型实际上是称为CarProxy的东西,它是 Entity Framework 使用反射创建的临时内存类型。这个“假”代理类的基类型是Car,并且具有所有原始Car属性,但包括一个称为LazyLoader的额外属性,用于可能需要它的属性。
如果您进一步检查这种“假” CarProxy类型,您还将看到Assembly.IsDynamic = true,这表明该类是使用反射动态创建的(请参阅文档):
var TheCar = DBContext.Cars.Find(1);
Console.WriteLine(TheCar.GetType().Assembly.IsDynamic.ToString()); //will echo "true"
幸运的是,Newtonsoft.Json对JsonConvert.SerializeObject()方法有一个覆盖,它允许我们提供一个基本类型,因此生成的 JSON 不包含该类型中不存在的属性。因此,要消除LazyLoader属性,只需提供对象的 BaseType 作为类型参数:
var TheCar = DBContext.Cars.Find(1);
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType);
为确保在序列化时不会出现任何循环引用循环(使用延迟加载时的可能性非常高),请使用以下设置调用序列化程序:
var TheCar = DBContext.Cars.Find(1);
var Settings = new Newtonsoft.Json.JsonSerializerSettings
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType, Settings);
注意:当序列化程序遍历对象时,这可能仅适用于第一级深度。如果您提供给序列化程序的对象还有更多延迟加载子属性,则“LazyLoader”属性可能会再次出现。我没有测试过,所以我不能肯定。
我知道这是旧的,但添加
public boolean ShouldSerializeLazyLoader() { return false; }
到你想要序列化的那些树下的所有类,你将得到一个惰性加载器免费的 JSON。
参考:https ://www.newtonsoft.com/json/help/html/ConditionalProperties.htm
该问题的检查答案仅适用于根对象,如果我们有许多嵌套的延迟加载对象,则此解决方案将不起作用。虽然@ Marcello-Barbiani的答案是正确的,但是将这个功能添加到我们拥有的所有实体中并不是一个好方法。
最好的方法是创建一个派生自 DefaultContractResolver 的新 ContractResolver 并检查属性是否为 Lazyloader 然后跳过它,如下所示:
public class NonLazyloaderContractResolver : DefaultContractResolver
{
public new static readonly NonLazyloaderContractResolver Instance = new NonLazyloaderContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.PropertyName == "LazyLoader")
{
property.ShouldSerialize = i => false;
}
return property;
}
}
之后添加上面的类在序列化对象时通过 JsonSerializerSettings 传递它:
var json = JsonConvert.SerializeObject(newProduct, new JsonSerializerSettings() {
ContractResolver = new NonLazyloaderContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore });
最后,如果您使用的是 asp.net core 或 asp.net core webapi,请将此合同添加为 startup.cs 文件中的默认contractresolver:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new NonLazyloaderContractResolver();
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});