C# 基于C中的条件从JSON中删除元素#

C# 基于C中的条件从JSON中删除元素#,c#,json,json.net,C#,Json,Json.net,我有一个JSON字符串,我希望能够在C#中修改它。当其中一个子值是某个值时,我希望能够删除一组数据 采取以下措施 { "responseHeader":{ "status":0, "QTime":0, "params":{ "explainOther":"", "fl":"*,score", "indent":"on", "start":"0", "q":"*:*", "hl.fl":"",

我有一个JSON字符串,我希望能够在C#中修改它。当其中一个子值是某个值时,我希望能够删除一组数据

采取以下措施

 {
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "explainOther":"",
      "fl":"*,score",
      "indent":"on",
      "start":"0",
      "q":"*:*",
      "hl.fl":"",
      "qt":"",
      "wt":"json",
      "fq":"",
      "version":"2.2",
      "rows":"2"}
  },
  "response":{"numFound":2,"start":0,"maxScore":1.0,"docs":
  [{
        "id":"438500feb7714fbd9504a028883d2860",
        "name":"John",
        "dateTimeCreated":"2012-02-07T15:00:42Z",
        "dateTimeUploaded":"2012-08-09T15:30:57Z",
        "score":1.0
   },
   {
        "id":"2f7661ae3c7a42dd9f2eb1946262cd24",
        "name":"David",
        "dateTimeCreated":"2012-02-07T15:02:37Z",
        "dateTimeUploaded":"2012-08-09T15:45:06Z",
        "score":1.0
    }]
 }}
上面显示了两个响应结果。我希望能够在其子“id”值匹配时删除整个父响应结果组,例如,如果我的id为“2F7661AE3C7A42DD9F2EB19462CD24”,我希望删除第二个组,因此我的结果如下所示

{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "explainOther":"",
      "fl":"*,score",
      "indent":"on",
      "start":"0",
      "q":"*:*",
      "hl.fl":"",
      "qt":"",
      "wt":"json",
      "fq":"",
      "version":"2.2",
      "rows":"2"}},
  "response":{"numFound":2,"start":0,"maxScore":1.0,"docs":[
  {
        "id":"438500feb7714fbd9504a028883d2860",
        "name":"John",
        "dateTimeCreated":"2012-02-07T15:00:42Z",
        "dateTimeUploaded":"2012-08-09T15:30:57Z",
        "score":1.0
    }]
  }}
我需要对Json文件执行多个删除操作。Json文件可能包含数千个结果,我真的需要尽可能高性能的方法

非常感谢您的帮助。

var jObj=(JObject)JsonConvert.DeserializeObject(json);
var jObj = (JObject)JsonConvert.DeserializeObject(json);
HashSet<string> idsToDelete = new HashSet<string>() { "2f7661ae3c7a42dd9f2eb1946262cd24" };

jObj["response"]["docs"]
    .Where(x => idsToDelete.Contains((string)x["id"]))
    .ToList()
    .ForEach(doc=>doc.Remove());

var newJson = jObj.ToString();
HashSet idsToDelete=new HashSet(){“2f7661ae3c7a42dd9f2eb19462cd24”}; jObj[“响应”][“文档”] .Where(x=>idsToDelete.Contains((字符串)x[“id”])) 托利斯先生() .ForEach(doc=>doc.Remove()); var newJson=jObj.ToString();
在过去10分钟左右的时间里,我一直试图将其压缩成一个更好的LINQ语句,但事实上,已知ID列表本质上改变了每个元素的求值方式,这意味着我可能无法实现这一点

        var jObj = (JObject)JsonConvert.DeserializeObject(json);
        var docsToRemove = new List<JToken>();
        foreach (var doc in jObj["response"]["docs"])
        {
            var id = (string)doc["id"];
            if (knownIds.Contains(id))
            {
                docsToRemove.Add(doc);
            }
            else
            {
                knownIds.Add(id);
            }
        }
        foreach (var doc in docsToRemove)
            doc.Remove();
var jObj=(JObject)JsonConvert.DeserializeObject(json);
var docsToRemove=新列表();
foreach(jObj[“响应”][“单据”]中的var单据)
{
变量id=(字符串)文档[“id”];
if(knownIds.Contains(id))
{
docsToRemove.Add(doc);
}
其他的
{
添加(id);
}
}
foreach(docsToRemove中的var文档)
doc.Remove();
这似乎适用于我准备测试的糟糕的小控制台应用程序,但我的测试仅限于上面的示例数据,因此如果有任何问题,请继续并留下评论,以便我可以修复它们


值得一提的是,这基本上是以线性时间运行的,与你输入的元素数量有关,这可能是你在没有搞笑这个问题的情况下获得的更多算法性能。使用task Parallel Library将每页约100条记录旋转到自己的任务中,调用一个工作者来处理自己的小页面并返回清理后的JSON字符串。如果你在多核机器上运行它,这肯定会加快速度,我很乐意为你提供一些代码,让你开始这方面的工作,但这对于问题的范围来说也是一个巨大的过度工程。

上面的答案对我都不起作用,我不得不
中删除()
子代(
.Parent.Remove()
)不仅仅是
Remove()
它。下面的工作代码示例:

namespace Engine.Api.Formatters
{
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Formatting;
    using System.Net.Http.Headers;
    using System.Threading.Tasks;
    using System.Web.Script.Serialization;
    using System.Xml;
    using System.Xml.Serialization;

    public class ReducedJson
    {
        public dynamic WriteToStreamAsync(object value)
        {
                    var json = new JavaScriptSerializer().Serialize(value);
                    var serializedJson = (JObject)JsonConvert.DeserializeObject(json);
                    foreach (var response in serializedJson["ProductData"]["Motor"]["QuoteResponses"])
                    {
                        response["NetCommResults"].Parent.Remove();
                        foreach (var netCommResult in response["BestPriceQuote"]["NetCommResults"])
                        {
                            netCommResult["Scores"].Parent.Remove();
                        }
                    }

          return serializedJson;
        }
}

希望这能为您节省一些时间。

我刚刚找到另一个答案

var aJson = JsonConvert.DeserializeObject<JObject>(json);
var doc = aJson["response"]["docs"];
JObject docs = new JObject();
docs["docs"] = doc;

// remove
docs.SelectTokens(string.Format("docs[?(@.id == '{0}')]", "2f7661ae3c7a42dd9f2eb1946262cd24")).ToList().ForEach(i => i.Remove());
// replace
aJson.SelectToken("response.docs").Replace(docs["docs"]);
var aJson=JsonConvert.DeserializeObject(json);
var doc=aJson[“响应”][“文档”];
JObject docs=新的JObject();
单据[“单据”]=单据;
//除去
docs.SelectTokens(string.Format(“docs[?(@.id=='{0}')],“2F7661AE3C7A42DD9F2EB19462CD24”)).ToList().ForEach(i=>i.Remove());
//替换
aJson.SelectToken(“response.docs”).Replace(docs[“docs”);

如果你一次读入整个JSON流,你会担心内存会被耗尽吗?这是一个好消息,但结果很可能会被分页到更易于管理的位置,比如说一页100个结果。有没有过这样的情况,你必须回滚一页才能找到要删除的内容?看起来不是这样,但我想确定。不,没有必要回滚OP希望对任何给定ID执行此操作,因此您必须保留一个已知ID的列表,并按顺序计算每个元素,如果
list.Contains(ID)则删除它们
返回为真…但是,这再次假定元素足够小,一个简单的
反序列化对象
调用不会导致
OutOfMemoryException
!@YYY我可以扩展答案以轻松删除多个ID,但您关于OOM的评论只是您的假设。您自己制造了问题,希望我回答我的问题t、 我只在问题中看到可能有成千上万的结果。呃,我不理解你的敌意-如果你检查这个问题,你会注意到我试图澄清内存限制,所以我可以尝试自己的答案。当被告知有数千行时,这是一个合理的问题。你是如何测试代码的?
doc[“id”]
抛出一个异常
无法访问Newtonsoft.Json.Linq.JProperty上的子值。
Hrm,这很奇怪。让我试着复制,看看粘贴代码时是否有什么愚蠢的地方我忽略了。哈哈,我有时真是个笨蛋。我从开发虚拟机上粘贴的内容过时了。这实际上是我第一次尝试使用ende时的代码显然,第一个错误是您应该枚举
[“docs”]
也是。代码的第一位中隐藏的另一个错误是,在枚举时不能修改
IEnumerable
。我花了一段时间再次查看我的答案,才意识到我的错误。现在更新!