166 votes

Le module json de Python convertit les clés du dictionnaire int en chaînes

J'ai constaté que quand le suivant est exécuté, python json module (inclus depuis 2.6) convertit int clés de dictionnaire pour les cordes.

>>> import json
>>> releases = {1: "foo-v0.1"}
>>> json.dumps(releases)
'{"1": "foo-v0.1"}'

Est-il un moyen facile de préserver la clé comme un int, sans avoir à analyser la chaîne de décharge et de charge. Je crois qu'il serait possible en utilisant les crochets fournis par le module json, mais encore une fois il faut quand même de l'analyse. Est-il éventuellement un argument que j'ai négligé? cheers, chaz

Sous-question: Merci pour les réponses. Voyant que json fonctionne comme je le craignais, est-il un moyen facile de transmettre un type de clé par peut-être l'analyse de la sortie de dumps? Aussi je note le code en faisant le dumping et le code de téléchargement de l'objet json à partir d'un serveur et de le charger, sont tous deux écrits par moi.

109voto

Jim Dennis Points 5454

C'est l'un de ces subtiles différences entre les divers cartographie des collections qui peuvent vous mordre.

En Python (et apparemment en Lua) les clés d'une cartographie (dictionnaire ou une table, respectivement) sont des références d'objet. En Python, ils doivent être immuables types, ou ils doivent être des objets qui mettent en oeuvre un __hash__ méthode. (Le Lua docs suggèrent qu'il utilise automatiquement l'objet d'identification d'un algorithme de hachage/clé même pour les objets mutables et s'appuie sur la chaîne de stage pour s'assurer que l'équivalent chaînes à la carte pour les mêmes objets).

En Perl, Javascript, awk et de nombreuses autres langues, les touches pour le hachage, tableaux associatifs ou ce qu'ils sont appelés pour la langue donnée, sont des chaînes de caractères (ou "scalaires" en Perl). En perl $foo{1}, $foo{1.0}, and $foo{"1"} sont toutes les références à la même cartographie en %foo --- la clé est évalué comme un scalaire!

JSON qui a commencé comme un Javascript de sérialisation de la technologie. (JSON est synonyme de [J]ava[S]cript [o]objet [n]introduction en bourse.) Naturellement, il implémente la sémantique pour sa cartographie de notation qui sont compatibles avec sa cartographie sémantique.

Si les deux extrémités de votre sérialisation vont être Python alors vous feriez mieux d'utiliser les cornichons. Si vous avez vraiment besoin de convertir ces dos de JSON en natif des objets Python je suppose que vous avez un couple de choix. D'abord, vous pourriez essayer (try: ... except: ...) pour la convertir en une touche à un numéro dans le cas d'un dictionnaire de recherche de panne. Alternativement, si vous ajoutez un code à l'autre extrémité (le sérialiseur ou générateur de cette de données JSON) puis vous pouvez faire effectuer une sérialisation JSON sur chacune des valeurs de la clé --- fournir ceux-ci comme une liste de clés. (Puis votre code Python serait d'abord parcourir la liste des clés, de l'instanciation/désérialisation en natif des objets Python ... et ensuite utiliser ces pour accéder aux valeurs de la cartographie).

59voto

bobince Points 270740

Non, la clé numérique n'existe pas en JavaScript. Toutes les propriétés de l'objet sont converties en chaîne.

 var a= {1: 'a'};
for (k in a)
    alert(typeof k); // 'string'
 

Cela peut conduire à des comportements curieux:

 a[999999999999999999999]= 'a'; // this even works on Array
alert(a[1000000000000000000000]); // 'a'
alert(a['999999999999999999999']); // fail
alert(a['1e+21']); // 'a'
 

Les objets JavaScript ne sont pas vraiment des mappages appropriés, comme vous le comprendriez dans des langages tels que Python, et l'utilisation de clés qui ne sont pas des chaînes donne un résultat étrange. C'est pourquoi JSON écrit toujours explicitement les clés sous forme de chaînes, même si cela ne semble pas nécessaire.

23voto

Ashish Points 275

Vous pouvez également essayer de convertir dictionnaire en une liste de formats [(k1, v1), (k2, v2)] tout en l'encodant à l'aide de json, puis de le reconvertir en dictionnaire après l'avoir décodé.

 
>>>> import json
>>>> json.dumps(releases.items())
    '[[1, "foo-v0.1"]]'
>>>> releases = {1: "foo-v0.1"}
>>>> releases == dict(json.loads(json.dumps(releases.items())))
     True
 

Je pense que cela nécessitera un peu plus de travail, comme avoir une sorte d'indicateur pour identifier tous les paramètres à convertir en dictionnaire après le décodage de json.

11voto

AFoglia Points 3791

J'ai pris de l'mordu par le même problème. Comme d'autres l'ont souligné, en JSON, le mappage de touches doivent être des chaînes de caractères. Vous pouvez faire une des deux choses. Vous pouvez utiliser une moins stricte librairie JSON, comme demjson, qui permet entier cordes. Si pas d'autres programmes (ou pas d'autres dans d'autres langues) sont ceux qui vont le lire, alors vous devriez être bien. Ou vous pouvez utiliser un autre sérialisation de la langue. Je ne dirais pas pickle. C'est dur à lire, et n'est pas conçu pour être sécurisé. Au lieu de cela, je vous suggère de YAML, qui est (presque) un sur-ensemble de JSON, et il ne permet pas d'entier clés. (Au moins PyYAML .)

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