我试图从我的python脚本执行jq命令。当我从终端(MacOs)执行时,jq命令工作正常。
cat filename.json |jq '{Name:.name, address:.address[0][1].street}'
基本上我试图使用jq从JSON中提取数据。由于JSON包含嵌套数组,我必须使用变量循环。
我的问题是 -
我不想使用除python之外的任何语言,因为它会导致兼容性问题。
答案 0 :(得分:11)
来自jq FAQ:
问:Python可以使用哪些绑定?
A:
pip install jq#有关详细信息,请参阅https://pypi.python.org/pypi/jq
pip install pyjq#有关详细信息,请参阅https://pypi.python.org/pypi/pyjq
对于你的嵌套数组,循环遍历它听起来像是可以(也许应该)在jq中完成的事情。
答案 1 :(得分:3)
是的,使用子流程。例如:
jsonFile = '/path/to/your/filename.json'
jq_cmd = "/bin/jq '{Name:.name, address:.address[0][1].street}' " + jsonFile
jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
# read JSON object, convert to string, store as a dictionary
jDict = json.loads(jq_proc.stdout.read())
jq_proc.stdout.close()
查看包含少量记录的JSON数据集会有所帮助。对于使用jq循环遍历python中的JSON集,很容易获得对象的计数然后迭代。一点点开销,但它使代码易于理解。
# count number of JSON records from the root level
jq_cmd = "/bin/jq '. | length' " + jsonFile
jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
jObjCount = int(jq_proc.stdout.read())
jq_proc.stdout.close()
# iterate over each root level JSON record
for ix in range(jObjCount):
jq_cmd = "jq '. | .[" + str(ix) + "]' " + jsonFile
jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
# read object, convert to string, store as a python dictionary
jDict = json.loads(jq_proc.stdout.read())
# iterate over nested objects within a root level object
# as before, count number items but here for each root level JSON object
jq_cmd = "/bin/jq '. | .[" + str(ix) + "].sub_Item_Key | length' " + jsonFile
jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
jItemCount = int(jq_proc.stdout.read())
jq_proc.stdout.close()
for jx in range(jItemCount):
jq_cmd = "/bin/jq '. | .[" + str(ix) + "].sub_Item_Key[" + str(jx) + "]' " + jsonFile
jq_proc = subprocess.Popen(jq_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
# read JSON item, convert to string, store as a python dictionary
jItemDict = json.loads(jq_proc.stdout.read())
享受!
答案 2 :(得分:3)
sh
模块可以轻松地从python调用jq子进程。 e.g。
import sh
cmd = sh.jq('-M', '{Name:.name, address:.address[0][1].street}', 'filename.json')
print "cmd returned >>%s<<" % cmd.stdout
答案 3 :(得分:3)
我相信公认的答案应该是Peak的答案,因为在python中使用C api的正确方法是通过python绑定库,并且https://pypi.python.org/pypi/jq和https://pypi.python.org/pypi/pyjq都应能按预期工作。 / p>
话虽这么说,由于我们正在谈论python,所以我想提出一个更具有pythonic的替代方法: glom (pip install glom
,https://glom.readthedocs.io/)>
使用jq
而不是像glom
中那样使用DSL,您只需使用纯python(此输出格式称为spec
)以所需的格式声明输出即可。在这种情况下,您需要一个简单的dict
:
spec = {'Name': 'name',
'street': 'address.0.1.street'}
然后只需对您的数据调用glom:
output_data = glom(input_data, spec)
就像jq
一样,您也可以在命令行上使用glom
:
cat filename.json | glom "{'Name': 'name', 'street': 'address.0.1.street'}"
完整的python示例:
import json
from pprint import pprint
from glom import glom
with open('filename.json', 'rt') as f:
input_data = json.load(f)
spec = {'Name': 'name',
'street': 'address.0.1.street'}
output_data = glom(input_data, spec)
pprint(output_data)
答案 4 :(得分:2)
嗯,我是jq的忠实粉丝,但看起来你似乎并没有做过一些在Python中也不容易做到的事情。考虑:
import json
with open("filename.json", "r") as f:
data = json.load(f)
{"Name": data["name"], "address": data["address"][0][1]["street"]}
答案 5 :(得分:0)