¿Cómo puedo comprobar si una cadena es JSON válida en Python?


En Python, ¿hay alguna forma de comprobar si una cadena es JSON válida antes de intentar analizarla?

Por ejemplo, trabajando con cosas como la API de Facebook Graph, a veces devuelve JSON, a veces podría devolver un archivo de imagen.

 117
Author: Martin Thoma, 2011-04-01

4 answers

Puede intentar hacer json.loads(), que lanzará un ValueError si la cadena que pasa no se puede decodificar como JSON.

En general, el "Python" filosofía para este tipo de situación se llama EAFP, de más Fácil Pedir Perdón que Permiso.

 161
Author: John Flatness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-18 17:01:14

Ejemplo Python script devuelve un booleano si una cadena es válida json:

import json

def is_json(myjson):
  try:
    json_object = json.loads(myjson)
  except ValueError, e:
    return False
  return True

Que imprime:

print is_json("{}")                          #prints True
print is_json("{asdf}")                      #prints False
print is_json('{ "age":100}')                #prints True
print is_json("{'age':100 }")                #prints False
print is_json("{\"age\":100 }")              #prints True
print is_json('{"age":100 }')                #prints True
print is_json('{"foo":[5,6.8],"foo":"bar"}') #prints True

Convertir una cadena JSON a un diccionario Python:

import json
mydict = json.loads('{"foo":"bar"}')
print(mydict['foo'])    #prints bar

mylist = json.loads("[5,6,7]")
print(mylist)
[5, 6, 7]

Convertir un objeto python a cadena JSON:

foo = {}
foo['gummy'] = 'bear'
print(json.dumps(foo))           #prints {"gummy": "bear"}

Si desea acceso a análisis de bajo nivel, no ruede el suyo propio, use una biblioteca existente: http://www.json.org /

Gran tutorial sobre el módulo JSON de python: https://pymotw.com/2/json /

 89
Author: Eric Leschinski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-11 01:39:27

Yo diría que el análisis es la única manera en que realmente se puede decir por completo. La excepción será generada por la función json.loads() de python (casi con certeza) si no es el formato correcto. Sin embargo, los propósitos de su ejemplo probablemente solo puede verificar el primer par de caracteres que no son espacios en blanco...

No estoy familiarizado con el JSON que facebook envía de vuelta, pero la mayoría de las cadenas JSON de aplicaciones web comenzarán con un cuadrado abierto [ o un corchete rizado {. No hay formatos de imágenes que conozco esos personajes.

Por el contrario, si sabe qué formatos de imagen pueden aparecer, puede verificar el inicio de la cadena en busca de sus firmas para identificar imágenes, y asumir que tiene JSON si no es una imagen.

Otro truco simple para identificar un gráfico, en lugar de una cadena de texto, en el caso de que esté buscando un gráfico, es simplemente probar caracteres no ASCII en el primer par de docenas de caracteres de la cadena (suponiendo que el JSON es ASCII).

 2
Author: Tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-29 06:48:17

Se me ocurrió una solución genérica e interesante para este problema:

class SafeInvocator(object):
    def __init__(self, module):
        self._module = module

    def _safe(self, func):
        def inner(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except:
                return None

        return inner

    def __getattr__(self, item):
        obj = getattr(self.module, item)
        return self._safe(obj) if hasattr(obj, '__call__') else obj

Y puedes usarlo así:

safe_json = SafeInvocator(json)
text = "{'foo':'bar'}"
item = safe_json.loads(text)
if item:
    # do something
 0
Author: odedlaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-29 06:48:55