Leer y escribir JSON en un archivo en Python

Introducción

En esta guía, veremos cómo leer y escribir datos JSON desde y hacia un archivo en Python, usando el json módulo.

JSON (notación de objetos JavaScript) es un formato extremadamente popular para la serialización de datos, dada su aplicación general y su ligereza, a la vez que es bastante amigable para los humanos. En particular, se usa ampliamente en el mundo del desarrollo web, donde probablemente encontrará objetos serializados en JSON que se envían desde API REST, configuración de aplicaciones o incluso almacenamiento de datos simple.

Dada su prevalencia, leer y analizar archivos JSON (o cadenas) es bastante común, y escribir JSON para enviarlos es igualmente común. En esta guía, veremos cómo aprovechar la json módulo para leer y escribir JSON en Python.

Escribir JSON en un archivo con Python con json.dump() y json.dumps()

Para escribir contenido JSON en un archivo en Python, podemos usar json.dump() y json.dumps(). Estos son métodos separados y lograr diferentes resultados:

  • json.dumps() – Serializa un objeto en formato JSON cadena
  • json.dump() – Serializó un objeto en un flujo JSON para guardarlo en archivos o sockets

Nota: La "s" en "dumps" es en realidad la abreviatura de "cadena de volcado".

El formato natural de JSON es similar a un mapa en ciencias de la computación: un mapa de key-value pares En Python, un diccionario es una implementación de mapa, por lo que naturalmente podremos representar JSON fielmente a través de un dict. Un diccionario puede contener otros diccionarios anidados, matrices, booleanos u otros tipos primitivos como enteros y cadenas.

:::

Nota: El incorporado json El paquete ofrece varios métodos convenientes que nos permiten convertir entre JSON y diccionarios.

:::

Dicho esto, importemos el json módulo, defina un diccionario con algunos datos y luego conviértalo en JSON antes de guardarlo en un archivo:

import json

data = {
    'employees' : [
        {
            'name' : 'John Doe',
            'department' : 'Marketing',
            'place' : 'Remote'
        },
        {
            'name' : 'Jane Doe',
            'department' : 'Software Engineering',
            'place' : 'Remote'
        },
        {
            'name' : 'Don Joe',
            'department' : 'Software Engineering',
            'place' : 'Office'
        }
    ]
}


json_string = json.dumps(data)
print(json_string)

Esto resulta en:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Aquí, tenemos un diccionario simple con algunos employees, cada uno de los cuales tiene un name, department y place. dumps() función de la json módulo vertederos un diccionario en contenido JSON y devuelve un Cadena JSON.

Una vez serializado, puede decidir enviarlo a otro servicio que lo deserializará o, por ejemplo, lo almacenará. Para almacenar esta cadena JSON en un archivo, simplemente abriremos un archivo en modo de escritura y lo anotaremos. Si no desea extraer los datos en una variable independiente para su uso posterior y simplemente desea volcarlos en un archivo, puede omitir el dumps() función y uso dump() instancia:


with open('json_data.json', 'w') as outfile:
    outfile.write(json_string)


with open('json_data.json', 'w') as outfile:
    json.dump(json_string, outfile)

Cualquier objeto similar a un archivo se puede pasar al segundo argumento del dump() función, incluso si no es un archivo real. Un buen ejemplo de esto sería un socket, que se puede abrir, cerrar y escribir como un archivo.

Leer JSON desde un archivo con Python con json.load() y json.loads()

La asignación entre el contenido del diccionario y una cadena JSON es sencilla, por lo que es fácil convertir entre los dos. La misma lógica que con dump() y dumps() es aplicado a load() y loads(). Muy parecido json.dumps(), el json.loads() La función acepta una cadena JSON y la convierte en un diccionario, mientras que json.load() te permite cargar en un archivo:

import json

with open('json_data.json') as json_file:
    data = json.load(json_file)
    print(data)

Esto resulta en:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Alternativamente, leamos una cadena JSON en un diccionario:

import json

python_dictionary = json.loads(json_string)
print(python_dictionary)

Lo que también resulta en:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Este es especialmente útil para analizar las respuestas de la API REST que envían JSON. Estos datos le llegan como una cadena, que luego puede pasar a json.loads() directamente, ¡y tendrá un diccionario mucho más manejable con el que trabajar!

Clasificación, Pretty-Printing, Separadores y Codificación

Al serializar sus datos a JSON con Python, el formato estándar que apunta a minimizar la memoria requerida para transmitir mensajes no es muy legible ya que se eliminan los espacios en blanco. Si bien este es el comportamiento ideal para la transferencia de datos (a las computadoras no les importa la legibilidad, pero sí el tamaño), a veces es posible que deba realizar pequeños cambios, como agregar espacios en blanco para que sea legible por humanos.

Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!

Nota: json.dump()/json.dumps() y json.load()/json.loads() todos proporcionan algunas opciones de formato.

Impresión bonita de JSON en Python

Hacer que JSON sea legible por humanos (también conocido como "bonita-impresión") es tan fácil como pasar un valor entero para el indent parámetro:

import json
data = {'people':[{'name': 'Scott', 'website': 'stackabuse.com', 'from': 'Nebraska'}]}
print(json.dumps(data, indent=4))

Esto crea una sangría de 4 espacios en cada nuevo bloque lógico:

{
    "people": [
        {
            "website": "stackabuse.com", 
            "from": "Nebraska", 
            "name": "Scott"
        }
    ]
}

Otra opción es utilizar la herramienta de línea de comandos: json.tool. Con él, puede imprimir bastante el JSON en la línea de comando sin afectar la cadena transmitida y solo afectar la forma en que se muestra en la tubería de salida estándar:

$ echo '{"people":[{"name":"Scott", "website":"stackabuse.com", "from":"Nebraska"}]}' | python -m json.tool
{
    "people": [
        {
            "name": "Scott",
            "website": "stackabuse.com"
            "from": "Nebraska",
        }
    ]
}

Ordenar objetos JSON por claves

En términos JSON:

“Un objeto es un conjunto desordenado de pares nombre/valor”.

El orden de las claves no está garantizado, pero es posible que deba aplicar el orden de las claves. Para lograr ordenar, puede pasar True En el correo electrónico “Su Cuenta de Usuario en su Nuevo Sistema XNUMXCX”. sort_keys opción al usar json.dump() or json.dumps():

import json
data = {'people':[{'name': 'Scott', 'website': 'stackabuse.com', 'from': 'Nebraska'}]}
print(json.dumps(data, sort_keys=True, indent=4))

Esto resulta en:

{
    "people": [
        {
            "from": "Nebraska",
            "name": "Scott",
            "website": "stackabuse.com"
        }
    ]
}

Texto y codificación ASCII

De forma predeterminada, json.dump() y json.dumps() se asegurará de que el texto en el diccionario de Python dado esté codificado en ASCII. Si hay caracteres que no son ASCII, se escapan automáticamente, como se muestra en el siguiente ejemplo:

import json
data = {'item': 'Beer', 'cost':'£4.00'}
jstr = json.dumps(data, indent=4)
print(jstr)
{
    "item": "Beer",
    "cost": "u00a34.00"
}

Esto no siempre es aceptable y, en muchos casos, es posible que desee mantener sus caracteres Unicode sin cambios. Para hacer esto, configure el ensure_ascii opción de False:

jstr = json.dumps(data, ensure_ascii=False, indent=4)
print(jstr)
{
    "item": "Beer",
    "cost": "£4.00"
}

Omitir tipos de datos clave personalizados

Si una clave en su diccionario es de un tipo no primitivo (str, int, float, bool or None), La TypeError se genera cuando intenta volcar contenido JSON en un archivo. Puede omitir estas teclas a través de la skipkeys argumento:

jstr = json.dumps(data, skipkeys=True)

Habilitación y deshabilitación de verificación circular

Si una propiedad de un objeto JSON hace referencia a sí mismo, o a otro objeto que hace referencia al objeto principal, se crea un JSON infinitamente recursivo. La recursividad infinita generalmente da como resultado que la memoria se asigne rápidamente hasta que un dispositivo se quede sin memoria y, en el caso de volcar JSON, un RecursionError se eleva y se detiene el vertido.

Esto está regulado por el check_circular bandera, que es True por defecto, y evita posibles problemas al escribir dependencias circulares. Para desactivarlo, puede establecerlo en `Falso:

jstr = json.dumps(data, check_circular=False)

Tenga en cuenta, sin embargo, que esto es altamente no recomendado.

Activación y desactivación de NaN

valores de NaN, tales como -inf, inf y nan puede infiltrarse en los objetos que desea serializar o deserializar. estándar JSON no permite para los valores de NaN, pero aún tienen un valor lógico que es posible que desee transmitir en un mensaje. Por otro lado, es posible que desee hacer cumplir los valores de NaN no está transmitido y generar una excepción en su lugar. los allow_nan la bandera está configurada en True por defecto, y le permite serializar y deserializar valores de NaN, reemplazándolos con los equivalentes de JavaScript (Inifinity, -Infinity y NaN).

Si establece la bandera en False en su lugar, cambiará a un formato estandarizado estrictamente JSON, lo que plantea un ValueError si sus objetos contienen atributos con estos valores:

jstr = json.dumps(data, allow_nan=False)

Cambio de separadores

En JSON, las claves se separan de los valores con dos puntos (:) y los elementos se separan entre sí con comas (,):

key1:value1,
key2:value2

Los separadores predeterminados para leer y escribir JSON en Python son (', ', ': ') espacios en blanco después de las comas y los dos puntos. Puede modificarlos para omitir los espacios en blanco y, por lo tanto, hacer que el JSON sea un poco más compacto, o cambiar completamente los separadores con otros caracteres especiales para una representación diferente:


jstr = json.dumps(data, separators=(',', ':'))

Problemas de compatibilidad con Python 2

Si está utilizando una versión anterior de Python (2.x), es posible que se encuentre con una TypeError al intentar volcar el contenido de JSON en un archivo. Es decir, si el contenido contiene un carácter no ASCII, un TypeError es elevado, aunque pasas el argumento de codificación, cuando usas el json.dump() método:


with open('json_data.json', 'w', encoding='utf-8') as outfile:
    json.dump(json_string, outfile, ensure_ascii=False)

Si encuentra este caso límite, que desde entonces se ha solucionado en versiones posteriores de Python, intente usar json.dumps() en su lugar, y escriba el contenido de la cadena en un archivo en lugar de transmitir el contenido directamente en un archivo.

Conclusión

En esta guía, le presentamos la json.dump(), json.dumps(), json.load()y json.loads() métodos, que ayudan a serializar y deserializar cadenas JSON.

Luego echamos un vistazo a cómo puede ordenar objetos JSON, imprimirlos de forma bonita, cambiar la codificación, omitir tipos de datos clave personalizados, habilitar o deshabilitar controles circulares y si se permiten NaN, así como también cómo cambiar los separadores para serialización y deserialización.

Dado que JSON es una de las formas más populares de serializar datos estructurados, es probable que deba interactuar con ellos con bastante frecuencia, especialmente cuando trabaja en aplicaciones web. de pitón json El módulo es una excelente manera de comenzar, aunque probablemente encontrará que simplejson es otra gran alternativa que es mucho menos estricta con la sintaxis JSON.

Sello de tiempo:

Mas de Abuso de pila