Este simple paquete se puede usar para corregir una cadena JSON inválida. Para conocer todos los casos en los que funcionará este paquete, consulte la prueba unitaria.
Si encuentra útil esta biblioteca, puede ayudarme donando hacia mi presupuesto mensual de cerveza aquí: https://github.com/sponsors/mangiucugna
Si no está seguro de si esta biblioteca soluciona su problema específico, o simplemente desea que su JSON valida en línea, puede visitar el sitio de demostración en las páginas de GitHub: https://mangiucugna.github.io/json_repair/
O escuche un Audio DeepDive generado por el cuaderno de Google para una introducción al módulo
Algunos LLM son un poco dudosos cuando se trata de devolver datos JSON bien formados, a veces se saltan entre paréntesis y a veces agregan algunas palabras, porque eso es lo que hace un LLM. Afortunadamente, los errores que cometen los LLM son lo suficientemente simples como para ser solucionados sin destruir el contenido.
Busqué un paquete Python liviano que pudiera solucionar de manera confiable este problema pero no pudo encontrar ninguno.
Entonces escribí uno
Como parte de mi trabajo, usamos API de OpenAI y notamos que incluso con la salida estructurada a veces el resultado no es un JSON completamente válido. Así que todavía usamos esta biblioteca para cubrir esos valores atípicos.
Instale la biblioteca con PIP
pip install json-repair
Entonces puede usarlo en su código como este
from json_repair import repair_json
good_json_string = repair_json(bad_json_string)
# If the string was super broken this will return an empty string
Puede usar esta biblioteca para reemplazar por completo json.loads()
:
import json_repair
decoded_object = json_repair.loads(json_string)
o simplemente
import json_repair
decoded_object = json_repair.repair_json(json_string, return_objects=True)
Algunos usuarios de esta biblioteca adoptan el siguiente patrón:
obj = {}
try:
obj = json.loads(string)
except json.JSONDecodeError as e:
obj = json_repair.loads(string)
...
Esto es un desperdicio porque json_repair
ya verificará para usted si el JSON es válido, si aún desea hacerlo, luego agregue skip_json_loads=True
a la llamada como se explica la sección a continuación.
JSON Repair proporciona también un reemplazo para json.load()
:
import json_repair
try:
file_descriptor = open(fname, 'rb')
except OSError:
...
with file_descriptor:
decoded_object = json_repair.load(file_descriptor)
y otro método para leer de un archivo:
import json_repair
try:
decoded_object = json_repair.from_file(json_file)
except OSError:
...
except IOError:
...
Tenga en cuenta que la biblioteca no captará ninguna excepción relacionada con el IO y que tendrá que ser administrada por usted
Cuando trabaja con caracteres no latinos (como chino, japonés o coreano), debe aprobar ensure_ascii=False
a repair_json()
para preservar los caracteres no latinos en la salida.
Aquí hay un ejemplo usando caracteres chinos:
repair_json("{'test_chinese_ascii':'统一码'}")
Volverá
{"test_chinese_ascii": "u7edfu4e00u7801"}
En su lugar, pasar ensure_ascii=False
:
repair_json("{'test_chinese_ascii':'统一码'}", ensure_ascii=False)
Volverá
{"test_chinese_ascii": "统一码"}
Si encuentra esta biblioteca demasiado lenta porque está usando json.loads()
puede omitirla pasando skip_json_loads=True
a repair_json
. Como:
from json_repair import repair_json
good_json_string = repair_json(bad_json_string, skip_json_loads=True)
Tomé la decisión de no usar ninguna biblioteca JSON rápida para evitar tener una dependencia externa, de modo que cualquiera pueda usarla independientemente de su pila.
Algunas reglas generales para usar:
return_objects=True
siempre será más rápido porque el analizador ya devuelve un objeto y no tiene serializar ese objeto a JSONskip_json_loads
es más rápido solo si sabe 100% que la cadena no es un JSON válidor"string with escaping""
Instale la biblioteca para la línea de comandos con:
pipx install json-repair
para conocer todas las opciones disponibles:
$ json_repair -h
usage: json_repair [-h] [-i] [-o TARGET] [--ensure_ascii] [--indent INDENT] filename
Repair and parse JSON files.
positional arguments:
filename The JSON file to repair
options:
-h, --help show this help message and exit
-i, --inline Replace the file inline instead of returning the output to stdout
-o TARGET, --output TARGET
If specified, the output will be written to TARGET filename instead of stdout
--ensure_ascii Pass ensure_ascii=True to json.dumps()
--indent INDENT Number of spaces for indentation (Default 2)
¡Por favor, fije esta biblioteca solo en la versión principal!
Usamos TDD y versiones semánticas estrictas, habrá actualizaciones frecuentes y no hay cambios de ruptura en versiones menores y de parches. Para asegurarse de fijar solo la versión principal de esta biblioteca en sus requirements.txt
, especifique el nombre del paquete seguido de la versión principal y un comodín para versiones menores y de parches. Por ejemplo:
json_repair==0.*
En este ejemplo, cualquier versión que comience con 0.
Será aceptable, permitiendo actualizaciones sobre versiones menores y de parches.
Si está utilizando esta biblioteca en su trabajo académico (como sé, muchas personas lo son), encuentre el bibtex aquí:
@software{Baccianella_JSON_Repair_-_2024,
author = {Baccianella, Stefano},
month = aug,
title = {{JSON Repair - A python module to repair invalid JSON, commonly used to parse the output of LLMs}},
url = {https://github.com/mangiucugna/json_repair},
version = {0.28.3},
year = {2024}
}
¡Gracias por citar mi trabajo y por favor envíeme un enlace al papel si puede!
Este módulo analizará el archivo JSON después de la definición BNF:
<json> ::= <primitive> | <container>
<primitive> ::= <number> | <string> | <boolean>
; Where:
; <number> is a valid real number expressed in one of a number of given formats
; <string> is a string of valid characters enclosed in quotes
; <boolean> is one of the literal strings 'true', 'false', or 'null' (unquoted)
<container> ::= <object> | <array>
<array> ::= '[' [ <json> *(', ' <json>) ] ']' ; A sequence of JSON values separated by commas
<object> ::= '{' [ <member> *(', ' <member>) ] '}' ; A sequence of 'members'
<member> ::= <string> ': ' <json> ; A pair consisting of a name, and a JSON value
Si algo está mal (una paréntesis o citas faltantes, por ejemplo), usará algunas heurísticas simples para arreglar la cadena JSON:
Estoy seguro de que faltarán algunos casos de esquina, si tiene ejemplos, por favor, abra un problema o incluso empuje mejor un PR
Simplemente cree un entorno virtual con requirements.txt
.
Asegúrese de que las acciones de GitHub que se ejecutan después de presionar un nuevo confirmación no fallen también.
Necesitará acceso al propietario a este repositorio
pyproject.toml
y actualizar el número de versión adecuadamente utilizando la notación semver
python -m build