234 votes

Comment vérifier si une chaîne est un JSON valide en Python ?

En Python, existe-t-il un moyen de vérifier si une chaîne est un JSON valide avant d'essayer de l'analyser ?

Par exemple, en travaillant avec des choses comme l'API Graphique de Facebook, parfois elle renvoie du JSON, parfois elle peut renvoyer un fichier image.

3 votes

L'api doit définir le type de contenu

4 votes

Vous ne pouvez pas spécifier quelles données sont renvoyées dans l'appel API ? Je ne suis pas familier avec l'API de Facebook mais cela semble vraiment étrange.

0 votes

Je l'ai fait une fois, mais avec codegolf chemin

285voto

John Flatness Points 14473

Vous pouvez essayer de faire json.loads() ce qui entraînera un ValueError si la chaîne que vous passez ne peut pas être décodée en JSON.

En général, les " Pythonique La philosophie de " l'esprit d'équipe " pour ce type de situation s'appelle EAFP pour Il est plus facile de demander le pardon que la permission .

4 votes

Je peux voir comment cela fonctionnera. Ce qui m'amène à ma prochaine question. Il jette une ValueError. Ce que je veux, à ce stade, c'est qu'il renvoie la chaîne de caractères incriminée pour que je puisse en faire autre chose. Jusqu'à présent, je n'ai obtenu que le message d'erreur et le type.

2 votes

Qu'y a-t-il de mal à renvoyer simplement la chaîne de caractères que vous avez passée à loads dans la clause d'exception ?

1 votes

Rien d'anormal, juste une erreur de débutant de ma part. Il semble que je ne puisse pas appeler file.read() deux fois. Mais je peux définir une variable et l'utiliser. Et c'est ce que j'ai fait.

183voto

Eric Leschinski Points 14289

Exemple Python script renvoie un booléen si une chaîne est un json valide :

import json

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

Qui 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

Convertit une chaîne JSON en un dictionnaire Python :

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

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

Convertit un objet python en chaîne JSON :

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

Si vous voulez accéder à l'analyse syntaxique de bas niveau, n'en faites pas une, utilisez une bibliothèque existante : http://www.json.org/

Excellent tutoriel sur le module JSON de Python : https://pymotw.com/2/json/

Est String JSON et montre les erreurs de syntaxe et les messages d'erreur :

sudo cpan JSON::XS
echo '{"foo":[5,6.8],"foo":"bar" bar}' > myjson.json
json_xs -t none < myjson.json

Imprimés :

, or } expected while parsing object/hash, at character offset 28 (before "bar}
at /usr/local/bin/json_xs line 183, <STDIN> line 1.

json_xs est capable de vérifier la syntaxe, d'analyser, de prendre en charge, d'encoder, de décoder et bien plus encore :

https://metacpan.org/pod/json_xs

0 votes

Pensez-vous que nous devrions del json_object une fois validée ?

4 votes

Pourquoi diable n'y a-t-il pas de méthode de validation appropriée ? Il devrait y avoir un moyen de vérifier les erreurs sans tuer les canaris.

0 votes

Ce que je veux dire, c'est que : Ce n'est pas parce que Python permet l'OO qu'il faut ignorer les autres parties. Je devrais avoir la possibilité soit A. de laisser la fonction échouer et d'utiliser les exceptions (la méthode OO/Python), soit B. d'appeler une fonction qui renvoie une valeur (succès ou erreur) au lieu de lancer une exception, puis de faire en sorte que ma fonction renvoie à son tour une valeur sentinelle qui indique une erreur, de sorte que les erreurs remontent la pile d'appels et puissent être utilisées si nécessaire (la méthode procédurale/C). Tout comme le C++ ne vous oblige pas à utiliser les exceptions (vous pouvez utiliser errno), Python ne devrait pas le faire non plus.

2voto

Tim Points 316

Je dirais que l'analyser est le seul moyen de le savoir. L'exception sera soulevée par la méthode de python json.loads() (presque certainement) si le format n'est pas correct. Cependant, pour les besoins de votre exemple, vous pouvez probablement vous contenter de vérifier les deux premiers caractères qui ne sont pas des espaces blancs...

Je ne suis pas familier avec le JSON que facebook renvoie, mais la plupart des chaînes JSON des applications web commencent par un carré ouvert. [ ou frisé { entre parenthèses. Aucun format d'image que je connais ne commence par ces caractères.

À l'inverse, si vous savez quels formats d'image sont susceptibles d'apparaître, vous pouvez vérifier le début de la chaîne pour trouver leur signature afin d'identifier les images, et supposer que vous avez du JSON s'il ne s'agit pas d'une image.

Une autre astuce simple pour identifier un graphique, plutôt qu'une chaîne de texte, dans le cas où vous recherchez un graphique, consiste à tester les caractères non ASCII dans les deux premières douzaines de caractères de la chaîne (en supposant que le JSON est ASCII).

0voto

odedlaz Points 11

J'ai trouvé une solution générique et intéressante à ce problème :

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

et vous pouvez l'utiliser comme ça :

safe_json = SafeInvocator(json)
text = "{'foo':'bar'}"
item = safe_json.loads(text)
if item:
    # do something

2 votes

Je pense que les solutions générales sont bonnes, mais dans ce cas, la except peut cacher toute exception sérieuse. La capture des exceptions doit être aussi restrictive que possible.

-1voto

Antony Points 31

Beaucoup plus simple dans le bloc try. Vous pouvez ensuite valider si le corps est un JSON valide.

async def get_body(request: Request):
try:
    body = await request.json()
except:
    body = await request.body()
return body

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X