Python - перетворення масиву байтів у формат JSON


81

Я хочу перетворити bytesмасив у формат JSON. Це джерело, яке я маю:

my_bytes_value = b'[{\'Date\': \'2016-05-21T21:35:40Z\', \'CreationDate\': \'2012-05-05\', \'LogoType\': \'png\', \'Ref\': 164611595, \'Classe\': [\'Email addresses\', \'Passwords\'],\'Link\':\'http://some_link.com\'}]'

І це бажаний результат, який я хочу отримати:

[{
"Date": "2016-05-21T21:35:40Z",
"CreationDate": "2012-05-05",
"LogoType": "png",
"Ref": 164611595,
"Classes": [
  "Email addresses",
  "Passwords"
],
"Link": "http://some_link.com"}]

Спочатку я перетворив байти в рядок:

my_new_string_value = my_bytes_value.decode("utf-8")

але коли я намагаюся завантажити до JSON:

my_json = json.loads(my_new_string_value)

Я отримую цю помилку:

json.decoder.JSONDecodeError: Expecting value: line 1 column 174 (char 173)

Насамперед. Байти до рядка, потім рядок до JSON
OneCricketeer

Я перетворив байти у рядок, використовуючи, .decode("utf-8")але коли я намагаюся перетворити рядок у JOSN, я отримую цю помилку json.decoder.JSONDecodeError: очікуване значення: рядок 1 стовпець 174 (char 173)
Меруан Бентамер

Чи можете ви оновити своє запитання відповідним кодом і роздрукувати декодований рядок?
OneCricketeer

1
І, звідки ви берете цей json?
OneCricketeer

6
@MerouaneBenthameur Причина, по якій це не вдається, полягає в тому, що рядок у вас не є JSON. Найбільш очевидним є те, що JSON використовує ", а не '.
чудернацький

Відповіді:


122

Ваш bytesоб'єкт є майже JSON, але він використовує одинарні лапки замість подвійних лапок, і це повинен бути рядок. Таким чином , один з способів виправити це є для декодування , bytesщоб strі замінити лапки. Інший варіант - використання ast.literal_eval; докладніше див. нижче. Якщо ви хочете роздрукувати результат або зберегти його у файлі як дійсний JSON, ви можете завантажити JSON до списку Python, а потім скинути його. Наприклад,

import json

my_bytes_value = b'[{\'Date\': \'2016-05-21T21:35:40Z\', \'CreationDate\': \'2012-05-05\', \'LogoType\': \'png\', \'Ref\': 164611595, \'Classe\': [\'Email addresses\', \'Passwords\'],\'Link\':\'http://some_link.com\'}]'

# Decode UTF-8 bytes to Unicode, and convert single quotes 
# to double quotes to make it valid JSON
my_json = my_bytes_value.decode('utf8').replace("'", '"')
print(my_json)
print('- ' * 20)

# Load the JSON to a Python list & dump it back out as formatted JSON
data = json.loads(my_json)
s = json.dumps(data, indent=4, sort_keys=True)
print(s)

вихід

[{"Date": "2016-05-21T21:35:40Z", "CreationDate": "2012-05-05", "LogoType": "png", "Ref": 164611595, "Classe": ["Email addresses", "Passwords"],"Link":"http://some_link.com"}]
- - - - - - - - - - - - - - - - - - - - 
[
    {
        "Classe": [
            "Email addresses",
            "Passwords"
        ],
        "CreationDate": "2012-05-05",
        "Date": "2016-05-21T21:35:40Z",
        "Link": "http://some_link.com",
        "LogoType": "png",
        "Ref": 164611595
    }
]

Як зазначає Антті Хаапала в коментарях, ми можемо використати ast.literal_eval для перетворення my_bytes_valueв список Python, як тільки ми розшифруємо його до рядка.

from ast import literal_eval
import json

my_bytes_value = b'[{\'Date\': \'2016-05-21T21:35:40Z\', \'CreationDate\': \'2012-05-05\', \'LogoType\': \'png\', \'Ref\': 164611595, \'Classe\': [\'Email addresses\', \'Passwords\'],\'Link\':\'http://some_link.com\'}]'

data = literal_eval(my_bytes_value.decode('utf8'))
print(data)
print('- ' * 20)

s = json.dumps(data, indent=4, sort_keys=True)
print(s)

Як правило, ця проблема виникає через те, що хтось зберігає дані, друкуючи її Python, reprзамість того, щоб використовувати jsonмодуль для створення належних даних JSON. Якщо це можливо, краще вирішити цю проблему, щоб спочатку створювалися належні дані JSON.


6
Я не вірю, що це рядок JSON, швидше репрез Python, тому використовуйте замість цього literal_eval
Antti Haapala

До речі, якщо ви хочете проаналізувати або пройти складну структуру JSON см stackoverflow.com/a/52414034/4014959 & stackoverflow.com/a/41778581/4014959
PM 2Ring


0

Щоб перетворити цей байт-масив безпосередньо в json, ви можете спочатку перетворити байт-масив у рядок із decode (), стандартним є utf-8. Змінити маркери лапок .. Останній крок - видалити "зі злитого рядка, змінити об'єкт json із рядка на список.

dumps(s.decode()).replace("'", '"')[1:-1]

0

Python 3.5 + Використовуйте модуль io

import json
import io

my_bytes_value = b'[{\'Date\': \'2016-05-21T21:35:40Z\', \'CreationDate\': \'2012-05-05\', \'LogoType\': \'png\', \'Ref\': 164611595, \'Classe\': [\'Email addresses\', \'Passwords\'],\'Link\':\'http://some_link.com\'}]'

fix_bytes_value = my_bytes_value.replace(b"'", b'"')

my_json = json.load(io.BytesIO(fix_bytes_value))  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.