我有一个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是"2f7661ae3c7a42dd9f2eb1946262cd24",我希望删除第二个组,因此我的结果如下。
{
"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文件可能包含数千个结果,我真的需要尽可能高的性能。
非常感谢您的帮助。
在过去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();
这似乎与我为测试而开发的糟糕的小控制台应用程序配合得很好,但我的测试仅限于上面的样本数据,所以如果有任何问题,请继续留言,这样我就可以修复它们。
就其价值而言,这将基本上以线性时间运行,与你输入的元素数量有关,这可能是你在不因这个问题而感到好笑的情况下获得的更多算法性能。脑海中浮现的是,使用任务并行库调用一个处理自己的小页面并返回清理后的JSON字符串的工作程序,将大约100条记录的每一页旋转到自己的任务中。如果你在多核机器上运行它,这肯定会让速度更快,我很乐意提供一些代码让你开始这方面的工作,但就目前的问题范围而言,这也是一个巨大的过度设计。
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();
上面的答案对我都不起作用,我必须从Parent
(.Parent.Remove()
)中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"]);