it-roy-ru.com

Есть ли способ выполнить JQ из Python

Я пытаюсь выполнить команду JQ из моего скрипта Python. В настоящее время команда jq работает нормально, когда я выполняю с терминала (MacOs).

cat filename.json |jq '{Name:.name, address:.address[0][1].street}'

В основном я пытаюсь извлечь данные из JSON с помощью jq. Поскольку JSON содержит вложенные массивы, мне пришлось бы зацикливаться с использованием переменной.

Мои вопросы - 

  • Могу ли я выполнить эту команду из скрипта Python
  • Если это можно сделать, то как бы я перебрал для вложенного массива 
  • элементы в данных образца дают выше (адрес [] []. улица)

Я не хочу использовать какой-либо язык, кроме Python, так как это может вызвать проблемы совместимости.

7
FirstName

От jq FAQ :

Q: Какие привязки доступны для Python?

A:

pip install jq # Подробнее см. https://pypi.python.org/pypi/jq

pip install pyjq # Подробнее см. https://pypi.python.org/pypi/pyjq

Что касается вашего вложенного массива, циклический просмотр его звучит как то, что можно (и, возможно, следует) сделать в jq. 

10
peak
  1. Могу ли я выполнить эту команду из скрипта Python

Да, используя подпроцесс. Пример:

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()
  1. Если это можно сделать, то как бы я перебрал для вложенного массива Элементы в приведенных выше примерах данных (address [] []. Street)

Это помогло бы увидеть набор данных JSON с несколькими записями. Для циклического прохождения наборов JSON в python с помощью jq легко получить количество объектов и затем выполнить итерацию. Небольшое количество накладных расходов, но это делает код легким для понимания.

# 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())

Наслаждайтесь!

3
endurogizer

Модуль sh облегчает вызов подпроцесса jq из python. например.

import sh
cmd = sh.jq('-M', '{Name:.name, address:.address[0][1].street}', 'filename.json')
print "cmd returned >>%s<<" % cmd.stdout
2
jq170727

Что ж, я большой поклонник jq, но не похоже, что вы делаете что-то, что не так просто сделать в Python. Рассматривать:

import json

with open("filename.json", "r") as f:
    data = json.load(f)

{"Name": data["name"], "address": data["address"][0][1]["street"]}
2
user3899165