C# 如何确定JSON对象是否只包含特定键?
我有一个JSON对象。我想确定它是否只包含一个特定的键。代码如下:C# 如何确定JSON对象是否只包含特定键?,c#,json,linq,json.net,except,C#,Json,Linq,Json.net,Except,我有一个JSON对象。我想确定它是否只包含一个特定的键。代码如下: { "Name": "ThirdParty", "Categories": [ { "Name": "Identity" }, { "Name": "Contact Information", "Mandatory": true, "Fields": [ { "Name": "P
{
"Name": "ThirdParty",
"Categories": [
{ "Name": "Identity" },
{
"Name": "Contact Information",
"Mandatory": true,
"Fields": [
{ "Name": "Phones" },
{ "Name": "Faxes" },
{ "Name": "Emails" }
]
},
{ "Name": "Addresses" },
{ "Name": "Bank Accounts" }
]
}
我想确定每个类别是否只包含Name
键。使用,我相信解决方案应该如下所示:
foreach(dynamic category in jObject.Categories)
{
var result = category.Children().Except(/* What goes here? */).Any();
}
但是在方法中除了()
之外,应该包含什么呢?有更好的方法吗?谢谢
注意:这不是以下问题的重复:
一个简单的
,其中
可以:
var categoriesWithMoreThanJustName = JObject.Parse(json)["Categories"]
.Where(category => category.Values<JProperty>().Any(property => property.Name != "Name"));
var categoriesWithMoreThanJustName=JObject.Parse(json)[“Categories”]
.Where(category=>category.Values().Any(property=>property.Name!=“Name”);
您始终可以使用来计算作业对象的属性。您需要具有一个属性的对象,名为“Name”
:
但是,这种方法存在一个问题:使用Except()
不能满足您所声明的需要
。。。确定每个类别的是否只包含名称
键
除了(…)。Any()
将测试除名称
之外是否还有其他键,但不会测试名称
键本身是否存在,因为它将被过滤掉。因此,空的JSON对象{}
将被错误地接受
相反,您需要检查序列是否相等,例如:
foreach (var category in jObject["Categories"].OfType<JObject>())
{
var result = category.Properties()
.Select(p => p.Name)
.SequenceEqual(new [] { "Name" });
}
foreach(类型()的jObject[“Categories”]中的变量类别)
{
var result=category.Properties()
.Select(p=>p.Name)
.SequenceEqual(新[]{“名称”});
}
如果您要求存在多个键,因为JSON对象是一组无序的名称/值对,根据,您可以对它们进行排序,以要求无序的序列相等:
var requiredKeys = new [] { "Name" } // Add additional required keys here
.OrderBy(n => n, StringComparer.Ordinal).ToArray();
foreach (var category in jObject["Categories"].OfType<JObject>())
{
var result = category.Properties()
.Select(p => p.Name)
.OrderBy(n => n, StringComparer.Ordinal)
.SequenceEqual(requiredKeys);
}
var requiredKeys=new[]{“Name”}//在此处添加其他所需键
.OrderBy(n=>n,StringComparer.Ordinal).ToArray();
foreach(类型()的jObject[“Categories”]中的var类别)
{
var result=category.Properties()
.Select(p=>p.Name)
.OrderBy(n=>n,StringComparer.Ordinal)
.SequenceEqual(所需密钥);
}
或者,如果您愿意,您可以使用,然后
但是,在我看来,如果您只需要检查一个JSON对象是否只包含一个指定的键,那么最初的解决方案是最简单和最具声明性的
演示小提琴2 不使用动态的另一种解决方案是创建与JSON结构匹配的C#模型,然后使用LINQ过滤所需的类别
模型:
public class Data
{
public string Name { get; set; }
public List<Category> Categories { get; set; }
}
public class Category
{
[JsonIgnore]
public bool HasNameOnly
{
get
{
return !string.IsNullOrEmpty(Name)
&& !Mandatory.HasValue
&& (Fields == null || !Fields.Any());
}
}
public string Name { get; set; }
public bool? Mandatory { get; set; }
public List<Field> Fields { get; set; }
}
public class Field
{
public string Name { get; set; }
}
为什么要投否决票?我该如何改进这个问题?@dbc-谢谢。我编辑了这个问题以满足你的建议。现在可以了吗?@Sipo-我不明白为什么有人会认为这是这些问题的重复,因为语言不同。但是,这样做肯定更好。所以如果我没弄错的话,您的结果将是名称为“身份”、“地址”和“银行帐户”的类别?@dbc-谢谢。我经常遇到这样的情况:人们只看了题目,就急忙把这个问题标为重复题。因为我们不应该在标题中添加标签,所以我没有在标题中指定这个问题是关于C的。这就是为什么我把便条放在最上面的原因,这样人们就不会无缘无故地把它标记为重复的。谢谢,这个解决方案很有效,所以我对这个答案投了更高的票。然而,对我来说,它似乎并不优雅,因为与(…).Any()相比,它的声明性还不够。除了(…)之外,我是否应该选择。任何()
解决方案,我需要在括号中添加什么?再次感谢!
var requiredKeys = new [] { "Name" } // Add additional required keys here
.OrderBy(n => n, StringComparer.Ordinal).ToArray();
foreach (var category in jObject["Categories"].OfType<JObject>())
{
var result = category.Properties()
.Select(p => p.Name)
.OrderBy(n => n, StringComparer.Ordinal)
.SequenceEqual(requiredKeys);
}
public class Data
{
public string Name { get; set; }
public List<Category> Categories { get; set; }
}
public class Category
{
[JsonIgnore]
public bool HasNameOnly
{
get
{
return !string.IsNullOrEmpty(Name)
&& !Mandatory.HasValue
&& (Fields == null || !Fields.Any());
}
}
public string Name { get; set; }
public bool? Mandatory { get; set; }
public List<Field> Fields { get; set; }
}
public class Field
{
public string Name { get; set; }
}
string json = @"{
""Name"": ""ThirdParty"",
""Categories"": [
{ ""Name"": ""Identity"" },
{
""Name"": ""Contact Information"",
""Mandatory"": true,
""Fields"": [
{ ""Name"": ""Phones"" },
{ ""Name"": ""Faxes"" },
{ ""Name"": ""Emails"" }
]
},
{ ""Name"": ""Addresses"" },
{ ""Name"": ""Bank Accounts"" }
]
}";
Data data = JsonConvert.DeserializeObject<Data>(json);
List<Category> categories = data.Categories.Where(x => x.HasNameOnly).ToList();