我有一个像这样的JSON的JObject:
{"name" : "user1", "groups" : ["group 1", "group2"]}
我想删除名称中的一个组。所以我有这样的代码:
JObject userJson = JObject.Parse(user);
JArray groups = userJson["groups"] as JArray;
JToken group = new JValue (groupName);
groups.Remove(group);
然而,方法JArray.remove(Jtoken item)返回false(表示无法删除)。这里的信息是:
https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JArray_Remove.htm
因此尝试设置JToken group = new JValue (groupName);
JToken group = new JValue (groupName); as JToken
和JValue group = new JValue (groupName);
等参数但它不起作用:S
这家伙解释JToken等级非常好,但我不知道我做得对不对。
答案 0 :(得分:2)
基本问题是JToken
层次结构是双重连接图。也就是说,每个令牌都知道它的Parent
,并且每个父令知道它的Children
。实际上,如果您将已经拥有父级的令牌添加到父级,则会对其进行克隆,如here所述。
因此,由于每个令牌都知道它的父节点,当您尝试从父节点中删除令牌时,Json.NET可能会执行以下两种操作之一:
事实上,Json.NET选择了前一个选项。 Jarray.Remove(JToken item)
调用JContainer.RemoveItem()
调用JArray.IndexOfItem()
来确定要删除的项的索引。反过来,此方法使用引用相等:
internal override int IndexOfItem(JToken item)
{
return _values.IndexOfReference(item);
}
由于您的JToken group = new JValue (groupName)
不属于JArray groups
,因此不会将其删除。
那么,您有什么选择按值删除JSON数组项?你可以:
使用LINQ搜索:
groups.Where(i => i.Type == JTokenType.String && (string)i == groupName).ToList().ForEach(i => i.Remove());
使用JTokenEqualityComparer
搜索,可用于搜索复杂对象和原始值:
var comparer = new JTokenEqualityComparer();
groups.Where(i => comparer.Equals(i, group)).ToList().ForEach(i => i.Remove());
使用SelectTokens()
搜索:
userJson.SelectTokens(string.Format("groups[?(@ == '{0}')]", groupName)).ToList().ForEach(i => i.Remove());
SelectTokens()
支持JSONPath query syntax,可以通过数组搜索匹配的项目。
最后,关于RemoveItem()
documentation的说明。它声明(斜体添加):
<强>
JArray.Remove Method (JToken)
强>从JArray中删除特定对象的第一个次出现。
由于我们已经看到在添加到父级时克隆了具有父级的令牌,因此似乎在给定父级中只能出现一次任何令牌。但文件似乎暗示不然;我猜想这个特定的文档句子是过时的,并且可以追溯到早期版本的Json.NET,其中同一个令牌可以多次出现在父级中。
答案 1 :(得分:0)
using System;
using System.Runtime.InteropServices;
namespace question
{
[StructLayout(LayoutKind.Explicit)]
public struct Union {
[FieldOffset(0)]
Int64 field2;
}
class Program
{
[DllImport("libcrash.so")]
static extern Union crash(string s);
static void Main(string[] args)
{
crash("boom !!");
Console.WriteLine("All Done");
}
}
}