Почему JSON не читается, если написано с отступом в PYTHON 3.8 - PullRequest
1 голос
/ 14 июля 2020

С отступом:

a_dict = ({"name": "kevin", "id":100001 })
with open('test.json',"a+") as f:
    json.dump(a_dict, f, indent=4) # Indent makes it more readable
    f.write("\n")
print("done")

Вывод, как показано ниже, невозможно будет прочитать, говорит json .decoder.JSONDecodeError: Ожидается имя свойства, заключенное в двойные кавычки:

{
    "name": "kevin",
    "id": 100001
}
{
    "name": "kevin",
    "id": 100001
}

Без отступа:

a_dict = ({"name": "kevin", "id":100001 })
with open('test.json',"a+") as f:
    json.dump(a_dict, f) # Indent makes it more readable
    f.write("\n")
print("done")

Вывод, который можно прочитать:

{"name": "kevin", "id": 100001}
{"name": "kevin", "id": 100001}
{"name": "kevin", "id": 100001}
{"name": "kevin", "id": 100001}

Расшифровка:

p_list = []
with open('test.json') as f:
    for json_obj in f:
        test_dict = json.loads(json_obj)
        p_list.append(test_dict)
        # print(test_dict)
for emp in p_list:
    print(emp['name'])

1 Ответ

2 голосов
/ 14 июля 2020

Похоже, вы пытаетесь использовать формат JSONL / JSON Lines . Предикат для этого формата состоит в том, что каждый объект или какая-либо JSON сущность полностью представлена ​​в одной строке файла. Таким образом, у вас не может быть JSONL и с отступом / предустановкой одновременно.

Когда вы это делаете:

with open('test.json') as f:
    for json_obj in f:
        ...

каждый json_obj - это всего лишь один строки файла, а не объекта JSON, считываемого до конца этого объекта.

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

Ближайшее к возможности JSON Lines & Pretty'fied - это команда jq инструмент линии . И поскольку это не пакет Python, для чтения и записи данных используйте subprocess.run() с capture_output=True.

Вы можете найти вопросы, связанные с этим инструментом, в StackOverflow с тег .

Редактировать: Если вы уверены, что будете записывать в файл только JSON объектов одинаковым образом всегда , вы можете настроить чтение так, чтобы оно начиналось со строки, которая начинается с { без любые пробелы / отступ перед ним и продолжайте читать, пока не дойдете до строки с } без каких-либо пробелов / отступов перед ним.

Примерное представление:

with open('test.json') as f:
    parts = []
    in_obj = False
    for some_text in f:
        if some_text == '{' and not in_obj:
            in_obj = True
            parts.append('{')
        elif in_obj:
            parts.append(some_text)
            if some_text == '}':
                in_obj = False
                # put this in a try-except block
                json_obj = json.loads('\n'.join(parts))
                yield json_obj  # or return
                parts = []  # reset
            elif not some_text.startswith(' ' * 4):
                print('error')  # in an object but wrong indent
                # the check above should actually include checking more than
                # just the starting 4 spaces since it could be nested further
        else:
            print('error')  # not in an object and not end delimeter

Вам нужно будет измените это, чтобы читать несколько объектов и быть фактическим анализатором.

Кроме того, как указано в @ ewen-lbh ниже, файлы в этом формате должны иметь расширение .jsonl. Если это .json, вы подразумеваете, что он содержит единственную допустимую загружаемую сущность json.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...