使用 Python 解析 JSON?

pra*_*upd 20 bash python json

我有一个 JSON 文件members.json,如下所示。

{
   "took": 670,
   "timed_out": false,
   "_shards": {
      "total": 8,
      "successful": 8,
      "failed": 0
   },
   "hits": {
      "total": 74,
      "max_score": 1,
      "hits": [
         {
            "_index": "2000_270_0",
            "_type": "Medical",
            "_id": "02:17447847049147026174478:174159",
            "_score": 1,
            "_source": {
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
               "memberFirstName": "Uri",
               "memberMiddleName": "Prayag",
               "memberLastName": "Dubofsky"
            }
         }, 
         {
            "_index": "2000_270_0",
            "_type": "Medical",
            "_id": "02:17447847049147026174478:174159",
            "_score": 1,
            "_source": {
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcG",
               "memberFirstName": "Uri",
               "memberMiddleName": "Prayag",
               "memberLastName": "Dubofsky"
            }
         }
      ]
   }
}
Run Code Online (Sandbox Code Playgroud)

我想使用bash脚本解析它只获取字段列表memberId

预期的输出是:

memberIds
----------- 
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
Run Code Online (Sandbox Code Playgroud)

我尝试将以下 bash+python 代码添加到.bashrc

function getJsonVal() {
   if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
       echo "Usage: getJsonVal 'key' < /tmp/file";
       echo "   -- or -- ";
       echo " cat /tmp/input | getJsonVal 'key'";
       return;
   fi;
   cat | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["'$1'"]';
}
Run Code Online (Sandbox Code Playgroud)

然后调用:

$ cat members.json | getJsonVal "memberId"
Run Code Online (Sandbox Code Playgroud)

但它抛出:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
KeyError: 'memberId'
Run Code Online (Sandbox Code Playgroud)

参考

/sf/answers/1511657521/

Ant*_*hon 28

如果你会使用:

 $ cat members.json | \
     python -c 'import json,sys;obj=json.load(sys.stdin);print obj;'
Run Code Online (Sandbox Code Playgroud)

您可以检查嵌套字典的结构,obj并看到您的原始行应为:

$ cat members.json | \
    python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hits"]["hits"][0]["_source"]["'$1'"]';
Run Code Online (Sandbox Code Playgroud)

到那个“memberId”元素。通过这种方式,您可以将 Python 保持为单行。

如果嵌套的“hits”元素中有多个元素,那么您可以执行以下操作:

$ cat members.json | \
python -c '
import json, sys
obj=json.load(sys.stdin)
for y in [x["_source"]["'$1'"] for x in obj["hits"]["hits"]]:
    print y
'
Run Code Online (Sandbox Code Playgroud)

Chris Down 的解决方案更适合在任何级别找到(唯一)键的单个值。

在我打印出多个值的第二个示例中,您正在使用单行代码达到您应该尝试的限制,在这一点上,我认为没有理由在 bash 中进行一半的处理,并且将转向完整的 Python 解决方案.


jor*_*anm 9

在 bash 中执行此操作的另一种方法是使用jshon。这是使用以下方法解决您的问题的方法jshon

$ jshon -e hits -e hits -a -e _source -e memberId -u < foo.json
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
Run Code Online (Sandbox Code Playgroud)

-e选项从JSON中提取值。在-a迭代的阵列上方和-u最终串进行解码。


Chr*_*own 6

好吧,您的密钥显然不在对象的根目录中。尝试这样的事情:

json_key() {
    python -c '
import json
import sys

data = json.load(sys.stdin)

for key in sys.argv[1:]:
    try:
        data = data[key]
    except TypeError:  # This is a list index
        data = data[int(key)]

print(data)' "$@"
}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是不仅仅是简单地将语法注入 Python,这可能会导致损坏(或更糟的是,任意代码执行)。

然后你可以这样称呼它:

json_key hits hits 0 _source memberId < members.json
Run Code Online (Sandbox Code Playgroud)


小智 5

另一种选择是jq

$ cat members.json | jq -r '.hits|.hits|.[]|._source|.memberId'
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
Run Code Online (Sandbox Code Playgroud)