Python Language
Módulo JSON
Buscar..
Observaciones
Para obtener la documentación completa, incluida la funcionalidad específica de la versión, consulte la documentación oficial .
Los tipos
Valores predeterminados
El módulo json
manejará la codificación y decodificación de los siguientes tipos de manera predeterminada:
Tipos de serialización:
JSON | Pitón |
---|---|
objeto | dictado |
formación | lista |
cuerda | str |
número (int) | En t |
numero (real) | flotador |
verdadero Falso | Verdadero Falso |
nulo | Ninguna |
El módulo json
también entiende NaN
, Infinity
e -Infinity
como sus valores flotantes correspondientes, que están fuera de la especificación JSON.
Tipos de serialización:
Pitón | JSON |
---|---|
dictado | objeto |
lista, tupla | formación |
str | cuerda |
Enums, float, (int / float) -derived | número |
Cierto | cierto |
Falso | falso |
Ninguna | nulo |
Para no permitir la codificación de NaN
, Infinity
e -Infinity
, debe codificar con allow_nan=False
. Esto generará un ValueError
si intenta codificar estos valores.
Personalización (des) serialización
Existen varios enlaces que le permiten manejar datos que deben representarse de manera diferente. El uso de functools.partial
permite aplicar parcialmente los parámetros relevantes a estas funciones para su comodidad.
Publicación por entregas:
Puede proporcionar una función que opere en objetos antes de que se serialicen así:
# my_json module
import json
from functools import partial
def serialise_object(obj):
# Do something to produce json-serialisable data
return dict_obj
dump = partial(json.dump, default=serialise_object)
dumps = partial(json.dumps, default=serialise_object)
De serialización:
Hay varios enlaces que son manejados por las funciones json, como object_hook y parse_float. Para obtener una lista exhaustiva de su versión de python, consulte aquí .
# my_json module
import json
from functools import partial
def deserialise_object(dict_obj):
# Do something custom
return obj
def deserialise_float(str_obj):
# Do something custom
return obj
load = partial(json.load, object_hook=deserialise_object, parse_float=deserialise_float)
loads = partial(json.loads, object_hook=deserialise_object, parse_float=deserialise_float)
Mayor (des) serialización personalizada:
El módulo json
también permite la extensión / sustitución de json.JSONEncoder
y json.JSONDecoder
para manejar varios tipos. Los ganchos documentados anteriormente se pueden agregar como valores predeterminados creando un método de nombre equivalente. Para usarlos, simplemente pase la clase como el parámetro cls
a la función relevante. El uso de functools.partial
permite aplicar parcialmente el parámetro cls a estas funciones por conveniencia, por ejemplo,
# my_json module
import json
from functools import partial
class MyEncoder(json.JSONEncoder):
# Do something custom
class MyDecoder(json.JSONDecoder):
# Do something custom
dump = partial(json.dump, cls=MyEncoder)
dumps = partial(json.dumps, cls=MyEncoder)
load = partial(json.load, cls=MyDecoder)
loads = partial(json.loads, cls=MyDecoder)
Creando JSON desde el dictado de Python
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
json.dumps(d)
El fragmento de código anterior devolverá lo siguiente:
'{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
Creando el dictado de Python desde JSON
import json
s = '{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
json.loads(s)
El fragmento de código anterior devolverá lo siguiente:
{u'alice': 1, u'foo': u'bar', u'wonderland': [1, 2, 3]}
Almacenamiento de datos en un archivo
El siguiente fragmento de código codifica los datos almacenados en d
en JSON y los almacena en un archivo (reemplace el filename
con el nombre real del archivo).
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
with open(filename, 'w') as f:
json.dump(d, f)
Recuperando datos de un archivo
El siguiente fragmento de código abre un archivo codificado JSON (reemplaza el filename
con el nombre real del archivo) y devuelve el objeto que está almacenado en el archivo.
import json
with open(filename, 'r') as f:
d = json.load(f)
`load` vs` loads`, `dump` vs` dumps`
El módulo json
contiene funciones para leer y escribir en y desde cadenas de Unicode, y para leer y escribir en y desde archivos. Estos se diferencian por una s
final en el nombre de la función. En estos ejemplos, usamos un objeto StringIO, pero las mismas funciones se aplicarían a cualquier objeto similar a un archivo.
Aquí usamos las funciones basadas en cadenas:
import json
data = {u"foo": u"bar", u"baz": []}
json_string = json.dumps(data)
# u'{"foo": "bar", "baz": []}'
json.loads(json_string)
# {u"foo": u"bar", u"baz": []}
Y aquí usamos las funciones basadas en archivos:
import json
from io import StringIO
json_file = StringIO()
data = {u"foo": u"bar", u"baz": []}
json.dump(data, json_file)
json_file.seek(0) # Seek back to the start of the file before reading
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
json_file.seek(0) # Seek back to the start of the file before reading
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
Como puede ver, la principal diferencia es que al descargar datos json debe pasar el identificador de archivo a la función, en lugar de capturar el valor de retorno. También vale la pena señalar que debe buscar el inicio del archivo antes de leer o escribir, para evitar la corrupción de datos. Al abrir un archivo, el cursor se coloca en la posición 0
, por lo que lo siguiente también funcionaría:
import json
json_file_path = './data.json'
data = {u"foo": u"bar", u"baz": []}
with open(json_file_path, 'w') as json_file:
json.dump(data, json_file)
with open(json_file_path) as json_file:
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
with open(json_file_path) as json_file:
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
Tener las dos formas de tratar con los datos json le permite trabajar de manera idiomática y eficiente con los formatos que se basan en json, como json-per-line de pyspark
:
# loading from a file
data = [json.loads(line) for line in open(file_path).splitlines()]
# dumping to a file
with open(file_path, 'w') as json_file:
for item in data:
json.dump(item, json_file)
json_file.write('\n')
Llamando a `json.tool` desde la línea de comandos a la salida JSON de impresión bonita
Dado un archivo JSON "foo.json" como:
{"foo": {"bar": {"baz": 1}}}
podemos llamar al módulo directamente desde la línea de comando (pasando el nombre del archivo como un argumento) para imprimirlo en forma bonita:
$ python -m json.tool foo.json
{
"foo": {
"bar": {
"baz": 1
}
}
}
El módulo también recibirá información de STDOUT, por lo que (en Bash) también podríamos hacer:
$ cat foo.json | python -m json.tool
Formato de salida JSON
Digamos que tenemos los siguientes datos:
>>> data = {"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Simplemente descartando esto como JSON no hace nada especial aquí:
>>> print(json.dumps(data))
{"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Configuración de sangría para obtener una salida más bonita
Si queremos una impresión bonita, podemos establecer un tamaño de indent
:
>>> print(json.dumps(data, indent=2))
{
"cats": [
{
"name": "Tubbs",
"color": "white"
},
{
"name": "Pepper",
"color": "black"
}
]
}
Ordenando las teclas alfabéticamente para obtener un resultado consistente
Por defecto, el orden de las teclas en la salida no está definido. Podemos obtenerlos en orden alfabético para asegurarnos de que siempre obtengamos la misma salida:
>>> print(json.dumps(data, sort_keys=True))
{"cats": [{"color": "white", "name": "Tubbs"}, {"color": "black", "name": "Pepper"}]}
Deshacerse de los espacios en blanco para obtener una salida compacta
Podríamos querer deshacernos de los espacios innecesarios, lo que se hace configurando cadenas separadoras diferentes de las predeterminadas ', '
y ': '
:
>>>print(json.dumps(data, separators=(',', ':')))
{"cats":[{"name":"Tubbs","color":"white"},{"name":"Pepper","color":"black"}]}
JSON que codifica objetos personalizados
Si solo intentamos lo siguiente:
import json
from datetime import datetime
data = {'datetime': datetime(2016, 9, 26, 4, 44, 0)}
print(json.dumps(data))
recibimos un error que dice que TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable
.
Para poder serializar correctamente el objeto de fecha y hora, necesitamos escribir un código personalizado sobre cómo convertirlo:
class DatetimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
try:
return obj.isoformat()
except AttributeError:
# obj has no isoformat method; let the builtin JSON encoder handle it
return super(DatetimeJSONEncoder, self).default(obj)
y luego use esta clase de codificador en lugar de json.dumps
:
encoder = DatetimeJSONEncoder()
print(encoder.encode(data))
# prints {"datetime": "2016-09-26T04:44:00"}