Je convertis une chaîne en objet json en utilisant la json-library:
a = '{"index":01}'
import json
json.loads(a)
>>> JSONDecodeError: Expecting ',' delimiter
Cependant, si je change à la place la chaîne a code> pour contenir un 0 de début, puis il se décompose:
a = '{"index":1}'
import json
json.loads(a)
{'index': 1}
Je pense que cela est dû au fait qu'il est JSON invalide si un entier commence par un zéro de début comme décrit dans ce fil .
Y a-t-il un moyen de remédier à cela? Sinon, alors je suppose que le meilleur moyen est de supprimer d'abord les zéros non significatifs par une expression régulière de la chaîne, puis de les convertir en json?
3 Réponses :
Premièrement, utiliser une expression régulière sur JSON est un mal, presque aussi mauvais que de tuer un chaton.
Si vous voulez représenter 01 comme une valeur JSON valide, envisagez d'utiliser cette structure: p>
a = '{"index" : "01"}'
import json
json.loads(a)
Si vous avez besoin que la chaîne littérale 01 se comporte comme un nombre, envisagez de la convertir simplement en un entier dans votre script Python.
Ma chaîne JSON est très longue et il n'est pas vraiment possible de le faire manuellement. Existe-t-il un moyen d'automatiser cela?
Je pense que le problème peut provenir de la source de votre chaîne JSON, plutôt que de votre code Python. Y a-t-il une chance que vous puissiez modifier l'exportation pour que les "nombres" soient traités comme des chaînes?
Pourquoi l'utilisation de regex serait-elle mauvaise? Si la chaîne n'a pas d'autres nombres, je pense que regex serait l'approche la plus simple pour cela
@ninesalt Le contenu JSON peut être imbriqué. Je ne peux pas donner un cas particulier où regex échouerait de plein fouet, mais je préférerais éviter cette chance.
J'obtiens la chaîne JSON d'une bibliothèque, donc je ne peux malheureusement pas la contrôler. Cependant, il n'est pas imbriqué, alors il est peut-être préférable d'écrire une expression régulière pour prendre soin des entiers?
Comment convertir une chaîne int JSON en véritable int avec json.loads S'il vous plaît voir le post ci-dessus Vous devez utiliser votre propre version de Decoder.
Plus d'informations peuvent être trouvées ici, dans le github https://github.com/simplejson/simplejson/blob/master/index. rst
>>> c = '{"value": 02}'
>>> import demjson
>>> demjson.decode(c)
{'value': 2}
Cela semble fonctionner .. C'est étrange
> >>> c = '{"value": 02}'
> >>> import json
> >>> value= json.loads(json.dumps(c))
> >>> print(value) {"value": 02}
> >>> c = '{"value": 0002}'
> >>> value= json.loads(json.dumps(c))
> >>> print(value) {"value": 0002}
Comme @Dunes, l'a souligné les charges produisent une chaîne comme résultat qui n'est pas une solution valide. Cependant,
DEMJSON semble le décoder correctement. https://pypi.org/project/demjson/ - méthode alternative
XXX
Parce que c est une chaîne et non un dictionnaire contenant un int. Les chaînes n'ont pas les mêmes restrictions que les nombres. Même si vous avez vidé un dictionnaire, cela n'aide toujours pas car le module json émettra un JSON valide, ce qui n'est pas le cas de 02 .
Un 0 au début d'un littéral de nombre dans JSON n'est pas valide sauf si le littéral de nombre est uniquement le caractère 0 ou commence par 0. . Le module Python json est assez strict en ce sens qu'il n'acceptera pas ces littéraux numériques. En partie parce qu'un 0 non significatif est parfois utilisé pour désigner la notation octale plutôt que la notation décimale. La désérialisation de ces numéros peut entraîner des erreurs de programmation involontaires. Autrement dit, doit 010 être analysé comme le nombre 8 (en notation octale) ou comme 10 (en notation décimale).
Vous peut créer un décodeur qui fera ce que vous voulez, mais vous devrez fortement pirater le module json ou réécrire une grande partie de ses composants internes. Quoi qu'il en soit, vous verrez un ralentissement des performances car vous n'utiliserez plus l'implémentation C du module.
Voici une implémentation qui peut décoder JSON qui contient des nombres avec n'importe quel nombre de zéros non significatifs. / p>
import json
import re
import threading
# a more lenient number regex (modified from json.scanner.NUMBER_RE)
NUMBER_RE = re.compile(
r'(-?(?:\d*))(\.\d+)?([eE][-+]?\d+)?',
(re.VERBOSE | re.MULTILINE | re.DOTALL))
# we are going to be messing with the internals of `json.scanner`. As such we
# want to return it to its initial state when we're done with it, but we need to
# do so in a thread safe way.
_LOCK = threading.Lock()
def thread_safe_py_make_scanner(context, *, number_re=json.scanner.NUMBER_RE):
with _LOCK:
original_number_re = json.scanner.NUMBER_RE
try:
json.scanner.NUMBER_RE = number_re
return json.scanner._original_py_make_scanner(context)
finally:
json.scanner.NUMBER_RE = original_number_re
json.scanner._original_py_make_scanner = json.scanner.py_make_scanner
json.scanner.py_make_scanner = thread_safe_py_make_scanner
class MyJsonDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# overwrite the stricter scan_once implementation
self.scan_once = json.scanner.py_make_scanner(self, number_re=NUMBER_RE)
d = MyJsonDecoder()
n = d.decode('010')
assert n == 10
json.loads('010') # check the normal route still raise an error
Je tiens à souligner que vous ne devriez pas vous fier à cela comme une solution appropriée. Il s'agit plutôt d'un hack rapide pour vous aider à décoder un JSON malformé qui est presque, mais pas tout à fait valide. C'est utile si la recréation du JSON sous une forme valide n'est pas possible pour une raison quelconque.
est-ce que seule la clé
indexest affectée par cela?@aws_apprentice Non, ce qui précède n'est qu'un exemple. Ma chaîne JSON est très longue, donc idéalement une fonction devrait être écrite pour mettre des guillemets autour de n'importe quel nombre de la chaîne (je suppose?)
Pouvez-vous partager un lien pastebin avec votre chaîne json?
vous devez utiliser votre propre décodeur Voir l'article similaire ici. stackoverflow.com/questions/45068797/...
@AbinayaDevarajan Qu'un nombre ne peut pas commencer par
0sauf s'il est seulement0ou commence par0.est assez fortement intégré dans lemodule json. La technique décrite dans la question ci-dessus ne fonctionne que sijsona reconnu que le nombre est un littéral de nombre JSON valide. Il est très difficile de contourner cette limitation, vous devez renoncer à utiliser une implémentation C du module internejson.scanner, et modifier une expression régulière globale dans l'implémentation Python du scanner. Ce qui est un hack assez laid.@Dunes, vous avez raison, j'ai essayé ce hack ..value = json.loads (json.dumps (c)) cela semble donner le résultat attendu, je suis confus.