根据嵌套值检索 Json 中的值
Retrieve a value in Json based on a nested value
我想检索给定特定 id 的投票,数据(对 govtrack.us) is stored in json and I am writing in python and intend to use js 的赞美。
例如输入 "Y000062" 应该产生 "Aye"
{
"bill": {
"congress": 114,
"type": "hr"
},
"category": "passage",
"votes": {
"Aye": [
{
"display_name": "Abraham",
"id": "A000374",
},
{
"display_name": "Yarmuth",
"id": "Y000062",
}
],
"Nay": [
{
"display_name": "Clyburn",
"id": "C000537",
},
]}}
在终端中,解决方案是 cat /ccc/114/votes/2015/H384/data.json | egrep 'Nay|Not Voting|Present|Yea|Aye|Y000062' | grep -B 1 'Y000062' |头-1
但是将其中继到 python 子流程似乎是一个笨拙的解决方案。
注意:在Json中,{}是一个对象,[]是一个数组
>>> d = {
... "bill": {
... "congress": 114,
... "type": "hr"
... },
... "category": "passage",
... "votes": {
... "Aye": [
... {
... "display_name": "Abraham",
... "id": "A000374",
... },
... {
... "display_name": "Yarmuth",
... "id": "Y000062",
... }
... ],
... "Nay": [
... {
... "display_name": "Clyburn",
... "id": "C000537",
... },
... ]}}
>>>
>>> # store lookup value in variable to more easily change later
... lookup_value = 'Y000062'
>>>
>>> # you're only concerned with the data in d['votes']
... for key, value in d['votes'].items():
... # for each 'display_name' in the each vote type ('Aye' or 'Nay')
... for element in value:
... if element['id'] == lookup_value:
... print(key)
...
Aye
>>>
下面是实现此功能的示例函数:
def get_vote_cast_from_id(id):
global my_json
for name, nested_values in my_json['votes'].items():
if any(nested_value['id'] == id for nested_value in nested_values):
return name
else:
return None
get_vote_cast_from_id("A000374")
# returns: "Aye"
get_vote_cast_from_id("random_id")
# returns: None
其中 my_json
是存储您的 JSON
对象的全局变量。
这里是三个使用jq的解决方案。如果一个人被限制只能投票一次,那么结果应该是一样的;否则,它们可能会有所不同,例如,如果一个人被记录为同时投票赞成和反对。
第一个解决方案假设每个人最多投票一次。如果满足这个假设,那么它也是最有效的,因为它使用 any/2
,它具有 "short-circuit" 语义:
$ jq --arg id Y000062 '.votes
| if any( .Aye[]; select(.id == $id) ) then "Aye"
elif any( .Nay[]; select(.id == $id) ) then "Nay"
else "none"
end' votes.json
下一个解决方案报告 "Aye" 每个出现在赞成名单上的个体,如果没有发现出现在赞成名单上的个体,则只继续对反对名单做同样的事情:
$ jq --arg id Y000062 '.votes
| ((.Aye[] | select(.id == $id) | "Aye") //
(.Nay[] | select(.id == $id) | "Nay")) ' votes.json
如果对个人可以出现在两个列表中的次数没有限制,第三种解决方案可能是合适的。它首先构造一个 [VOTE, ID] 对的流,然后选择感兴趣的 ID:
$ jq --arg id Y000062 '.votes
| ((.Nay[] | ["Nay", .id]),
(.Aye[] | ["Aye", .id])))
| select(.[1] == $id)
| .[0]' votes.json
对于给定的输入(稍作改动以使其有效 JSON),所有三个解决方案的输出为:
"Aye"
(您可以使用 hjson
等命令行工具将 JSON-with-extra-commas 转换为 JSON。)
这是一个使用 tostream
的 jq 解决方案
.votes
| tostream
| select(length==2) as [$p,$v]
| select($v == $id)
| $p[0]
如果此过滤器在 filter.jq
中并且示例数据在 data.json
中,则
jq -M --arg id Y000062 -f filter.jq data.json
生产
"Aye"
我想检索给定特定 id 的投票,数据(对 govtrack.us) is stored in json and I am writing in python and intend to use js 的赞美。
例如输入 "Y000062" 应该产生 "Aye"
{
"bill": {
"congress": 114,
"type": "hr"
},
"category": "passage",
"votes": {
"Aye": [
{
"display_name": "Abraham",
"id": "A000374",
},
{
"display_name": "Yarmuth",
"id": "Y000062",
}
],
"Nay": [
{
"display_name": "Clyburn",
"id": "C000537",
},
]}}
在终端中,解决方案是 cat /ccc/114/votes/2015/H384/data.json | egrep 'Nay|Not Voting|Present|Yea|Aye|Y000062' | grep -B 1 'Y000062' |头-1 但是将其中继到 python 子流程似乎是一个笨拙的解决方案。
注意:在Json中,{}是一个对象,[]是一个数组
>>> d = {
... "bill": {
... "congress": 114,
... "type": "hr"
... },
... "category": "passage",
... "votes": {
... "Aye": [
... {
... "display_name": "Abraham",
... "id": "A000374",
... },
... {
... "display_name": "Yarmuth",
... "id": "Y000062",
... }
... ],
... "Nay": [
... {
... "display_name": "Clyburn",
... "id": "C000537",
... },
... ]}}
>>>
>>> # store lookup value in variable to more easily change later
... lookup_value = 'Y000062'
>>>
>>> # you're only concerned with the data in d['votes']
... for key, value in d['votes'].items():
... # for each 'display_name' in the each vote type ('Aye' or 'Nay')
... for element in value:
... if element['id'] == lookup_value:
... print(key)
...
Aye
>>>
下面是实现此功能的示例函数:
def get_vote_cast_from_id(id):
global my_json
for name, nested_values in my_json['votes'].items():
if any(nested_value['id'] == id for nested_value in nested_values):
return name
else:
return None
get_vote_cast_from_id("A000374")
# returns: "Aye"
get_vote_cast_from_id("random_id")
# returns: None
其中 my_json
是存储您的 JSON
对象的全局变量。
这里是三个使用jq的解决方案。如果一个人被限制只能投票一次,那么结果应该是一样的;否则,它们可能会有所不同,例如,如果一个人被记录为同时投票赞成和反对。
第一个解决方案假设每个人最多投票一次。如果满足这个假设,那么它也是最有效的,因为它使用 any/2
,它具有 "short-circuit" 语义:
$ jq --arg id Y000062 '.votes
| if any( .Aye[]; select(.id == $id) ) then "Aye"
elif any( .Nay[]; select(.id == $id) ) then "Nay"
else "none"
end' votes.json
下一个解决方案报告 "Aye" 每个出现在赞成名单上的个体,如果没有发现出现在赞成名单上的个体,则只继续对反对名单做同样的事情:
$ jq --arg id Y000062 '.votes
| ((.Aye[] | select(.id == $id) | "Aye") //
(.Nay[] | select(.id == $id) | "Nay")) ' votes.json
如果对个人可以出现在两个列表中的次数没有限制,第三种解决方案可能是合适的。它首先构造一个 [VOTE, ID] 对的流,然后选择感兴趣的 ID:
$ jq --arg id Y000062 '.votes
| ((.Nay[] | ["Nay", .id]),
(.Aye[] | ["Aye", .id])))
| select(.[1] == $id)
| .[0]' votes.json
对于给定的输入(稍作改动以使其有效 JSON),所有三个解决方案的输出为:
"Aye"
(您可以使用 hjson
等命令行工具将 JSON-with-extra-commas 转换为 JSON。)
这是一个使用 tostream
的 jq 解决方案 .votes
| tostream
| select(length==2) as [$p,$v]
| select($v == $id)
| $p[0]
如果此过滤器在 filter.jq
中并且示例数据在 data.json
中,则
jq -M --arg id Y000062 -f filter.jq data.json
生产
"Aye"