2016-07-05 7 views
0

У меня есть следующий JSON-файл, который я получаю от API.Извлечение отдельных объектов JSON

{"Key-1":"Value-1", 
"Key-2":[{"Value-2"::Child_Value-1","Value-3":"Child_Value-2"}] 
} 
{"Key-21":"Value-21", 
"Key-22":[{"Value-22":"Child_Value-21","Value-23":"Child_Value-22"}] 
} 
{"Key-31":"Value-31", 
"Key-32":[{"Value-32":"Child_Value-31","Value-33":"Child_Value-32"}] 
} 

Я понимаю, что это не квалифицируется как формат JSON, но то, что я пытаюсь добиться, что я хочу, чтобы извлечь каждый из отдельных объектов и сохранять их в отдельный файл.

Например file1.json должен содержать -

[{"Key-1":"Value-1", 
    "Key-2":[{"Value-2":"Child_Value-1","Value-3":"Child_Value-2"}] 
    }] 

и file2.json должны содержать -

[{"Key-21":"Value-21", 
    "Key-22":[{"Value-22":"Child_Value-21","Value-23":"Child_Value-22"}] 
    }] 

Я пытаюсь сделать это с помощью питона и сценария оболочки, но это не ведет меня в любом месте. Есть ли хорошая библиотека в python/shell, которая поможет. Я отчасти ограничена на языке, которые будут использоваться (питон, скорлупа-скрипт)

+2

Насколько я знаю, нет библиотеки для разбора разбитого JSON (отсутствующие кавычки, а не один корневой массив/объект, ...). – jonrsharpe

+0

Если JSON хорошо сформирован, вы найдете [JSON module] (https://docs.python.org/2/library/json.html) для Python очень полезным. Плюс, я бы забыл о shell-скрипте ... – kazbeel

+0

Вам нужен какой-то метод для нахождения границ между отдельными битами JSON. Всегда ли это 3 линии на JSON? Это было бы идеально. – RemcoGerlich

ответ

0

Это именно то, что просит ваш вопрос (хотя я подозреваю, что это на самом деле не то, что вы хотите)

filecount = 0 
newfilecontents = '' 

with open('junksrc.txt', mode='r', encoding='utf-8') as src: 
    srclines = src.readlines() 
    for line in srclines: 
     if '{"Key' in line: 
      newfilecontents = '[' + line 
     if '}]' in line: 
      newfilecontents = newfilecontents + ' ' + line + ' }]\n' 
      filecount += 1 
      filename = 'junkdest' + str(filecount) + '.json' 
      with open(filename, mode='w', encoding='utf-8') as dest: 
       dest.write(newfilecontents) 
1

Вот что-то, что будет очень медленным и не оборудованным для обработки ошибок в данных, но это может сработать. Это генератор, который находит первый «{», а затем следующий »} и пытается разобрать бит между ними как JSON. Если это не удается, он ищет следующий '}' и пытается снова. Он дает успешно разобранные биты.

import json 

def generate_json_dictionaries(s): 
    opening = s.find('{') 
    while opening != -1: 
     possible_closing = opening 
     while True: 
      possible_closing = s.find('}', start=possible_closing+1) 
      if possible_closing == -1: return # Data incomplete 
      try: 
       j = json.loads(s[opening:possible_closing+1]) 
       yield j 
       break 
      except ValueError: 
       pass 
     opening = s.find('{', start=possible_closing+1) # Next start 

Не проверено.

0

Если вы получаете jq, вы можете препроцессировать свои данные в форму, которая легко разобрано из стандартной библиотеки JSON парсер:

$ jq -s '.' tmp.json 
[ 
    { 
    "Key-1": "Value-1", 
    "Key-2": [ 
     { 
     "Value-2": "Child_Value-1", 
     "Value-3": "Child_Value-2" 
     } 
    ] 
    }, 
    { 
    "Key-21": "Value-21", 
    "Key-22": [ 
     { 
     "Value-22": "Child_Value-21", 
     "Value-23": "Child_Value-22" 
     } 
    ] 
    }, 
    { 
    "Key-31": "Value-31", 
    "Key-32": [ 
     { 
     "Value-32": "Child_Value-31", 
     "Value-33": "Child_Value-32" 
     } 
    ] 
    } 
] 

jq может распознать поток действительных объектов верхнего уровня, так как у вас есть Вот. Опция -s сообщает jq, чтобы разместить их в одном массиве верхнего уровня перед дальнейшей обработкой.

+0

Это полезно. благодаря! есть ли способ дать массив, который вы создали с помощью команды jq, имя? Имеет ли jq дополнительные функции для такой операции? – FirstName

+0

Я не уверен, что вы подразумеваете под «дайте [это] имя». Один из способов его использования - связать его с вашим скриптом Python и использовать 'json.load' для чтения со стандартного ввода:' jq -s. TMP.json | python -c 'import sys, json; x = json.load (sys.stdin); ... '' – chepner

+0

То, что я имел в виду, назвав массив, это массив, который вы создали с помощью команды jq -s -« одиночный массив верхнего уровня ». Пример, который вы предоставили, создал массив верхнего уровня без имени. Я хочу знать, есть ли возможность создать с именем. – FirstName

Смежные вопросы