Convertir una matriz de bytes a formato JSON
Quiero analizar una bytes
cadena en formato JSON para convertirla en objetos de Python. Esta es la fuente que tengo:
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\'}]'
Y este es el resultado deseado que quiero tener:
[{
"Date": "2016-05-21T21:35:40Z",
"CreationDate": "2012-05-05",
"LogoType": "png",
"Ref": 164611595,
"Classes": [
"Email addresses",
"Passwords"
],
"Link": "http://some_link.com"}]
Primero, convertí los bytes en cadena:
my_new_string_value = my_bytes_value.decode("utf-8")
pero cuando intento invocarlo loads
para analizarlo como JSON:
my_json = json.loads(my_new_string_value)
Recibo este error:
json.decoder.JSONDecodeError: Expecting value: line 1 column 174 (char 173)
Su bytes
objeto es casi JSON, pero usa comillas simples en lugar de comillas dobles y debe ser una cadena. Entonces, una forma de solucionarlo es decodificar bytes
y str
reemplazar las comillas. Otra opción es utilizar ast.literal_eval
; consulte a continuación para obtener más detalles. Si desea imprimir el resultado o guardarlo en un archivo como JSON válido, puede cargar el JSON en una lista de Python y luego eliminarlo. P.ej,
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)
producción
[{"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
}
]
Como menciona Antti Haapala en los comentarios, podemos usar ast.literal_eval
para convertir my_bytes_value
a una lista de Python, una vez que la hayamos decodificado en una cadena.
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)
Generalmente, este problema surge porque alguien guardó datos imprimiendo su Python repr
en lugar de usar el json
módulo para crear datos JSON adecuados. Si es posible, es mejor solucionar ese problema para que, en primer lugar, se creen datos JSON adecuados.
Puedes simplemente usar,
import json
my_bytes_value = my_bytes_value.decode().replace("'", '"')
json.loads(my_bytes_value)
Python 3.5 + Usar módulo 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))
d = json.dumps(byte_str.decode('utf-8'))