Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用JToken处理空值时基于父条件选择子元素_C#_Json.net - Fatal编程技术网

C# 使用JToken处理空值时基于父条件选择子元素

C# 使用JToken处理空值时基于父条件选择子元素,c#,json.net,C#,Json.net,我正在尝试使用Newtonsoft和JTokens过滤我的JSON对象。我需要根据父元素的条件选择数组中的子元素。此外,将被筛选的数组可能有空的子元素 以下是JSON对象: { "level1": [{ "id": 1, "level2": [{ "attr": "attrvalue" }, { "attr": "attrvalue",

我正在尝试使用Newtonsoft和
JToken
s过滤我的JSON对象。我需要根据父元素的条件选择数组中的子元素。此外,将被筛选的数组可能有空的子元素

以下是JSON对象:

{
    "level1": [{
        "id": 1,
        "level2": [{
                "attr": "attrvalue"
            },
            {
                "attr": "attrvalue",
                "level3": [{
                        "attr1": "attr1value",
                        "level4": [{
                            "filterAttr": ["val1"],
                            "attr1": "attr1value"
                        }]
                    },
                    {
                        "attr1": "attr1value",
                        "level4": [{
                            "filterAttr": ["val1"],
                            "attr1": "attr1value",
                            "level5": [{
                                "key": "key",
                                "value": "value"
                            }]
                        }]
                    }
                ]
            }
        ]
    }]
}
我现在使用下面的代码来过滤上面的JSON。我需要根据
level4
val1
filteratr
level5
获取
键和

var jToken=jToken.Parse(json);
var key=jToken[“level1”]
.SelectMany(x=>x[“level2”])
。其中(x=>x[“level3”]!=null)
.SelectMany(x=>x[“level3”])
。其中(x=>x[“level4”]!=null)
.SelectMany(x=>x[“level4”])
.Where(x=>Convert.ToString(x[“filteratr”])==filterParam&&x[“level5”]!=null)
.SelectMany(x=>x[“level5”])
.Where(x=>Convert.ToString(x[“key”])==keyParam)
.选择(x=>x[“值”])
.First().ToString();
有没有比上面写的更好的方法来检查空值?
是否有更好的方法过滤父属性并获取子元素?

您可以使用一些技术来简化代码

  • 使用带有通配符表达式的
    SelectTokens()
    向下钻取到最低级别
    SelectTokens
    自动处理空值,因此如果路径上某个节点丢失,它将不会爆炸。您将获得与整个表达式或空枚举(如果没有)匹配的项
  • 创建扩展方法以帮助进行空检查,并在查询中使用这些方法。例如,您可以创建一个方法,该方法将检查
    JToken
    是否为null,如果不是,则检查它是否有与某些条件匹配的子项。e、 g:

        public static class JsonExtensions
        {
            public static bool HasAny(this JToken token, Func<JToken, bool> predicate)
            {
                return token != null && token.Children().Any(t => predicate(t));
            }
        }
    
    上述代码向下搜索以选择具有与
    keyParam
    匹配的
    keyParam
    键的
    level5
    的所有子级。然后它沿着链从那里走到
    level4
    ,查看
    filteratr
    是否有与
    filterParam
    匹配的子项。(此处需要三个
    .Parent
    ,因为包含
    属性的对象的父对象是数组,数组的父对象是属性
    level5
    ,该属性的父对象是包含
    filteratr
    的对象)如果有任何符合条件的项,我们从这些值返回第一个


    工作演示:

    谢谢。这很有帮助。有没有一个通用的方法来处理这个问题?就像循环所有元素,直到我找到键并检查是否有任何父项具有FilterATR?那么你是说
    键可以是任何级别,而不仅仅是
    级别5
    ,而
    filteratr
    可以在这上面的任何级别?我的意思是说,如果这是一个结构,我有另一个完全不同的结构,但是我写了一个通用方法,在这里我传入key和filter谓词,并得到传入key的值?将要传递的过滤器将定义层次结构。我仍然不完全清楚您要做什么,但听起来您希望能够在层次结构中向下和向上搜索。如果将JSON解析为一个
    JObject
    ,则可以使用
    substands()
    constances()
    扩展方法来帮助实现这一点。也许你在找什么?不,所以我要找的是一个方法,它将第一个参数作为键,即“key1”,第二个作为过滤器,如“level1/level2/level3/level4['filteratr']='filterParam'”,我的方法将基于此进行过滤,并从结果中找到第一个匹配的key1。
    string key = jToken.SelectTokens("level1[*].level2[*].level3[*].level4[*].level5[*]")
        .Where(x => (string)x["key"] == keyParam &&
                    x.Parent.Parent.Parent["filterAttr"].HasAny(y => (string)y == filterParam))
        .Select(x => (string)x["value"])
        .FirstOrDefault();