C# 如何确定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

我有一个JSON对象。我想确定它是否只包含一个特定的键。代码如下:

{
    "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();
}
但是在
方法中除了()
之外,应该包含什么呢?有更好的方法吗?谢谢


注意:这不是以下问题的重复:

  • (我的问题是关于C#,而不是JavaScript)

  • (我的问题是关于C#,不是jQuery,也不是关于对象中是否存在“字段名”,而是关于键是否是对象中唯一存在的键)


  • 一个简单的
    ,其中
    可以:

    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();