如何验证和删除 JSON 对象的嵌套节点

Posted

技术标签:

【中文标题】如何验证和删除 JSON 对象的嵌套节点【英文标题】:How to validate and remove nested nodes of JSON Object 【发布时间】:2019-12-31 17:48:12 【问题描述】:

我有下面的 JSON 对象

  
   "movieList":[  
        
         "movieID":1,
         "title":"TITLE 1",
         "showTimes":[  
              
               "date":"xx",
               "time":["11:00" , "15:00" ]
            ,
              
              "date":"xx",
               "time":["11:00"]
            ,
              
               "date":"xx",
               "time":["18:00" ]
            ,
              
              "date":"xx",
               "time":["11:00" , "15:00" , "18:00" ]
            
         ]
      
   ]

想要删除“showTimes”数组下的以下节点。在这里,我试图删除“时间”属性中没有值“18:00”的节点。

  
   "date":"xx",
   "time":["11:00" , "15:00" ]
,
  
  "date":"xx",
   "time":["11:00"]

使用下面的代码,我可以在 foreach 循环中获取时间值

 StreamReader rs = new StreamReader("xx.json"); 

  string json = rs.ReadToEnd();

  JObject jsonObject = JObject.Parse(json);

  JToken jToken = JToken.Parse(json);

 var result = jToken["movieList"].SelectMany(x => x["showTimes"].SelectMany(y => y["time"].Select(z => z)).ToList());

      foreach (var item in result)
        
          if (item.ToString() != "18:00")
              
                // item.Parent.Remove();
              
        

如何在 foreach 循环中从我的 JSON 对象中删除上述节点?

【问题讨论】:

我建议从 app.quicktype.io?share=8CYNaPjpEs2AKwfL0F2x 开始。 我不能在这里使用模型类,想将动态 JSON 返回到 UI。 time("18:00" ) 是修改我的 JSON 对象的输入参数 为什么不能从具体类中生成所需的 JSON? 我知道这感觉就像我没有帮助 - 但如果人们使用具体的类作为他们的起点,95% 的 JSON 问题将会消失。 请参阅此link 可能会有所帮助。不过我强烈推荐你@mjwills 评论 Removing an element from a JSON response的可能重复 【参考方案1】:

我也会建议使用模型类,但对于你的情况,这应该可以工作

 JObject jsonObject = JObject.Parse(json);
 JToken jToken = JToken.Parse(json);

 var result = jToken["movieList"].SelectMany(x => x["showTimes"]).ToList();

 foreach (var item in result)
 
   var times = item.SelectTokens("time").Values().ToList();    
   if (!times.Where(x => x.ToString().Trim() == "18:00").Any())
   
       item.Remove();
   
 

 var output = jToken.ToString(Formatting.Indented);   
 Console.WriteLine(output);

输出


  "movieList": [
    
      "movieID": 1,
      "title": "TITLE 1",
      "showTimes": [
        
          "date": "xx",
          "time": [
            "18:00"
          ]
        ,
        
          "date": "xx",
          "time": [
            "11:00",
            "15:00",
            "18:00"
          ]
        
      ]
    
  ]

【讨论】:

【参考方案2】:

您可以使用 Linq 及时查询不包含“18:00”的节点并删除它们。例如,

var jToken = JToken.Parse(json);
var result = jToken["movieList"].SelectMany(x=>x["showTimes"])
                            .Select(x=>x["time"])
                            .Where(x=>!x.Any(c=>c.Value<string>()=="18:00"))
                            .ToList();
foreach(var item in result)
     item.Parent.Parent.Remove();
var output = jToken.ToString(Newtonsoft.Json.Formatting.Indented);

样本输出


  "movieList": [
    
      "movieID": 1,
      "title": "TITLE 1",
      "showTimes": [
        
          "date": "xx",
          "time": [
            "18:00"
          ]
        ,
        
          "date": "xx",
          "time": [
            "11:00",
            "15:00",
            "18:00"
          ]
        
      ]
    
  ]

【讨论】:

【参考方案3】:

不要item.Parent.Remove(),试试item.Remove()

var json = "  \r\n   \"movieList\":[  \r\n        \r\n         \"movieID\":1,\r\n         \"title\":\"TITLE 1\",\r\n         \"showTimes\":[  \r\n              \r\n               \"date\":\"xx\",\r\n               \"time\":[\"11:00\" , \"15:00\" ]\r\n            ,\r\n              \r\n              \"date\":\"xx\",\r\n               \"time\":[\"11:00\"]\r\n            ,\r\n              \r\n               \"date\":\"xx\",\r\n               \"time\":[\"18:00\" ]\r\n            ,\r\n              \r\n              \"date\":\"xx\",\r\n               \"time\":[\"11:00\" , \"15:00\" , \"18:00\" ]\r\n            \r\n         ]\r\n      \r\n   ]\r\n";

var jToken = JToken.Parse(json);

var result = jToken["movieList"].SelectMany(x => x["showTimes"].SelectMany(y => y["time"].Select(z => z)).ToList());

foreach (var item in result)

    if (item.ToString() != "18:00")
    
        item.Remove();
    


var output = jToken.ToString(Formatting.Indented);

输出:


  "movieList": [
    
      "movieID": 1,
      "title": "TITLE 1",
      "showTimes": [
        
          "date": "xx",
          "time": []
        ,
        
          "date": "xx",
          "time": []
        ,
        
          "date": "xx",
          "time": [
            "18:00"
          ]
        ,
        
          "date": "xx",
          "time": [
            "18:00"
          ]
        
      ]
    
  ]

【讨论】:

你测试过这个吗?这看起来不像 OP 的要求 @ssilas777 是的,我确实测试过。它看起来不像 OP 的要求呢? 检查他想要的输出和你得到的输出 "date":"xx", "time":["18:00" ] , "date":"xx", "time":["11:00" , "15:00" , "18:00" ] .. 这应该是他的输出 @ssilas777 我把它读作 OP 想要删除不等于“18:00”的节点,这是他的代码示例正在尝试做的事情

以上是关于如何验证和删除 JSON 对象的嵌套节点的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 express-validator 对嵌套对象进行验证

如何在 ReactJS 中验证嵌套对象的 PropTypes?

iview 自定义验证表单多层嵌套如何实现

使用 Spring 验证器验证嵌套对象列表?

使用JSON模式验证protobuf消息?

由于嵌套 bean,无法在 playframework 中使用 GSON 解析 JSON