代码之家  ›  专栏  ›  技术社区  ›  Nishan

dotnet核心web api json响应包含不必要的元素

  •  0
  • Nishan  · 技术社区  · 8 年前

    我懒惰地将表数据加载到JSON结果中,并将它们温入前端应用程序。但当我得到这些数据时,我注意到在响应中存在不必要的元素和空元素。因此我 PUT 或者更新操作不适用于这些内部JSON属性。

       {
               "image":null,
               "paragraph":null,
               "question":{
                  "grid":null,
                  "elements":[
    
                  ],
                  "offeredAnswers":[
    
                  ],
                  "lazyLoader":{
    
                  },
                  "id":"1",
                  "text":"How can we serve you better?",
                  "type":"textarea",
                  "questionRequired":false,
                  "pageFlowModifier":false,
                  "gridId":null,
                  "min":null,
                  "max":null
               },
               "lazyLoader":{
    
               }
       }
    

    如果我改变 text ,不会更新,但如果我更改 paragraph 然后它将在数据库中更改。

    这里有一个新的房产叫做 lazyLoader 我也要把它处理掉。和 elements , offeredAnswers 因为它们是空的,所以确实不需要。我通过添加 virtual 引用类的关键字。

    public partial class Questions
    {
        public Questions()
        {
            Elements = new HashSet<Elements>();
            OfferedAnswers = new HashSet<OfferedAnswers>();
        }
    
    
        public string Id { get; set; }
        public string Text { get; set; }
        public string Type { get; set; }
        public bool QuestionRequired { get; set; }
        public bool PageFlowModifier { get; set; }
        public int? GridId { get; set; }
        public long? Min { get; set; }
        public long? Max { get; set; }
    
        public virtual Grids Grid { get; set; }
        public virtual ICollection<Elements> Elements { get; set; }
        public virtual ICollection<OfferedAnswers> OfferedAnswers { get; set; }
    }
    

    我有这条线 Startup.cs 停止引用循环处理的文件,因为如果没有该文件, POST 操作不工作,因为 JSON 我要发布的对象非常复杂,其中包含引用循环。

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                    .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
    

    我已经启用了延迟加载代理。

    services.AddDbContext<RDS_Context>
                (options => options.UseLazyLoadingProxies().UseSqlServer(connection));
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   er-sho    8 年前

    您可以通过迭代从JSON中删除空的 object 和 array

    类程序 { 静态void main(string[]args) { string json=file.readalltext(@“c:\users\xxx\source\repos\consoleapp4\consoleapp4\files\json6.json”); jobject data=jobject.parse(json); //从外部JSON获取所有具有值的子级都是空的 var result1=data.children<jproperty>() 。其中(x=>(x.value.type==jtokenType.object)&!x.value.hasvalues) 。 //从“question”对象中获取所有具有值的子级为空 var result2=data[“question”]。children<jproperty>() 。其中(x=>(x.value.type==jtokenType.object&!x.value.hasValues)(x.value.type==jtokenType.array&!x.value.hasvalues) 。 //移除上面的所有空对象或数组 结果1.foreach(x=>x.remove()); 结果2.foreach(x=>x.remove()); var obj=data.toobject<jobject>(); console.writeline(obj); console.readline(); } } < /代码>

    输出:

    注: 如果只想删除空的 lazyloader object through the json then use below lines in above code.

    从外部JSON获取值为空的“lazyloader”子级 var result1=data.children<jproperty>() 。其中(x=>x.value.type==jtokenType.object&!x.value.hasValues&&x.name=“Lazyloader”)。 。 //从“question”对象中获取值为空的“lazyloader”子级 var result2=data[“question”]。children<jproperty>() 。其中(x=>(x.value.type==jtokenType.object&!x.value.hasValues&&x.name=“Lazyloader”)) 。 < /代码>

    输出:

    class Program { static void Main(string[] args) { string json = File.ReadAllText(@"C:\Users\xxx\source\repos\ConsoleApp4\ConsoleApp4\Files\json6.json"); JObject data = JObject.Parse(json); //Getting all those children that have value are empty from outer json var result1 = data.Children<JProperty>() .Where(x => (x.Value.Type == JTokenType.Object) && !x.Value.HasValues) .ToList(); //Getting all those children that have value are empty from "question" object var result2 = data["question"].Children<JProperty>() .Where(x => (x.Value.Type == JTokenType.Object && !x.Value.HasValues) || (x.Value.Type == JTokenType.Array && !x.Value.HasValues)) .ToList(); //Remove all above empty object or arrays result1.ForEach(x => x.Remove()); result2.ForEach(x => x.Remove()); var obj = data.ToObject<JObject>(); Console.WriteLine(obj); Console.ReadLine(); } }

    输出:

    enter image description here

    注: 如果只想删除空的 lazyLoader 然后在上面的代码中使用下面的行。

    //Getting "lazyLoader" children that have value are empty from outer json
    var result1 = data.Children<JProperty>()
         .Where(x => x.Value.Type == JTokenType.Object && !x.Value.HasValues && x.Name == "lazyLoader")
         .ToList();
    
    //Getting "lazyLoader" children that have value are empty from "question" object
    var result2 = data["question"].Children<JProperty>()
         .Where(x => (x.Value.Type == JTokenType.Object && !x.Value.HasValues && x.Name == "lazyLoader"))
         .ToList();
    

    输出:

    enter image description here

        2
  •  2
  •   kaffekopp    8 年前

    可以将数据库实体模型与要在前端显示的模型分开。映射所需实体模型的属性,并将其包含到新的前端模型中。

    不实现新模型的快速方法是使用匿名对象,例如:

    myDbContext.MyObjects.Select(x => new { Prop1 = x.Property1, Prop2 = x.Property2 });
    

    如果您的实体类中真的有Lazyloader属性(例如,注入Ilazyloader as described here )你可以用 JsonIgnore attribtue .

        3
  •  1
  •   eduardomps    7 年前

    我知道已经有一个公认的答案了,但是基于 a suggestion at EFCore repos 和 another SO answer it referenced ,我将把这个替代方法留给那些只想摆脱Lazyloader属性的人。

    创建一个 自定义合同冲突解决程序.cs

    public class CustomContractResolver : DefaultContractResolver
    {
        public static CustomContractResolver Instance { get; } = new CustomContractResolver();
    
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);
            if (member.Name == "LazyLoader")
            {
                property.Ignored = true;
            }
            return property;
        }
    
    }
    

    修改你的 创业公司 , ConfigureServices 使用ContractResolver的方法

    services
        .AddMvc(...)
        .AddJsonOptions(options => {
            options.SerializerSettings.ContractResolver = CustomContractResolver.Instance;
        });