在JSON中通过JMESPath筛选值来搜索对象。

huangapple go评论123阅读模式
英文:

Search for an object in json by filtering on a value within that json using jmespath

问题

{
    "input": {
        "user": "john",
        "group": "johns_group"
    },
    "group_data": [
        {
            "name": "johns_group",
            "members": ["john", "michael"]
        },
        {
            "name": "sallys_group",
            "members": ["sally", "jane"]
        }
    ]
}

使用jmespath,您可以尝试以下表达式来检索具有指定名称的组:

group_data[?name == `input.group`]

这将检查group_data数组中的每个对象的name属性是否等于input.group中指定的组名。如果找到匹配的组,它将返回该组的对象。您可以进一步扩展此表达式以检查用户是否在该组的members列表中。

如果您的数据结构更复杂或不适用于上述表达式,请提供更多信息,以便我可以提供更具体的解决方案。

英文:

I have a json file that essentially looks like this:

{
    "input": {
        "user": "john",
        "group": "johns_group"
    },
    "group_data": [
        {
            "name": "johns_group",
            "members": ["john", "michael"]
        },
        {
            "name": "sallys_group",
            "members": ["sally", "jane"]
        }
    ]
}

Is it possible for me to retrieve the group under group_data with the name specified in input.group using jmespath?

I've tried the following:

group_data[?contains(name, input.group)]

But it doesn't work. If I just put in the group name however:

group_data[?contains(name, 'johns_group')]

It does work. But I can't just hardcode the names because the group_data, input.user, and input.group can all change.

If this isn't possible in pure jmespath with the way I've set it up, I have control over the structure of group_data and can change it to be more jmespath friendly. My end goal is to be able to retrieve the group object and then return a bool if input.user is in its members list.

答案1

得分: 1

短答案:这是不可能的。

详细信息:

  • 如果你输入 group_data,你将不再看到同一级别的其他字典。你必须将这样的引用放入一个变量中,我认为。例如,在Python中
import jmespath
import json
import yaml

with open('data.json', 'r') as myfile:
    data = myfile.read()
s = json.loads(data)
result = jmespath.search(f"group_data[?name == `{s['input']['group']}`].members", s)
print(yaml.dump(result))

产生的结果(以YAML格式)

- - john
  - michael

在Shell中,你可以编写一个过滤器。例如,

shell> cat filter.sh
#!/bin/sh
data=`paste -`
input_group=$(echo $data | jp -u "input.group")
group_data=$(echo $data | jp -u "group_data[?name == '$input_group'].members")
printf "$group_data"

它产生相同的结果(以JSON格式)

shell> cat data.json | ./filter.sh
[
  [
    "john",
    "michael"
  ]
]
  • 你说你可以改变结构。我认为在 group_data 中使用字典更适合这个用例。
shell> cat data-dict.json
{
    "group_data": {
        "johns_group": [
            "john",
            "michael"
        ],
        "sallys_group": [
            "sally",
            "jane"
        ]
    },
    "input": {
        "group": "johns_group",
        "user": "john"
    }
}

你可以在不使用 jmespath 的情况下引用该值。例如,在Python中

with open('data-dict.json', 'r') as myfile:
    data = myfile.read()
s = json.loads(data)
print(yaml.dump(s))

result = s['group_data']
展开收缩
['group']]
print(yaml.dump(result))

产生

- john
- michael
英文:

Short answer: It is not possible.

Details:

  • If you enter group_data you don't see other dictionaries at the same level anymore. You have to put such a reference into a variable, I think. For example, in Python
import jmespath
import json
import yaml


with open('data.json', 'r') as myfile:
    data = myfile.read()
s = json.loads(data)
result = jmespath.search(f"group_data[?name == `{s['input']['group']}`].members", s)
print(yaml.dump(result))

gives (in YAML)

- - john
  - michael

In a shell, you can write a filter. For example,

shell> cat filter.sh
#!/bin/sh
data=`paste -`
input_group=$(echo $data | jp -u "input.group")
group_data=$(echo $data | jp -u "group_data[?name == '$input_group'].members")
printf "$group_data"

which gives the same result (in JSON)

shell> cat data.json | ./filter.sh
[
  [
    "john",
    "michael"
  ]
]
  • You say you can change the structure. Dictionaries in group_data would serve the use-case better, I think
shell> cat data-dict.json
    {
        "group_data": {
            "johns_group": [
                "john",
                "michael"
            ],
            "sallys_group": [
                "sally",
                "jane"
            ]
        },
        "input": {
            "group": "johns_group",
            "user": "john"
        }
    }

You can reference the value without jmespath. For example, in Python

with open('data-dict.json', 'r') as myfile:
    data = myfile.read()
s = json.loads(data)
print(yaml.dump(s))

result = s['group_data']
展开收缩
['group']]
print(yaml.dump(result))

gives

- john
- michael

huangapple
  • 本文由 发表于 2023年8月5日 05:52:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76839276.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定