J'ai trouvé que lorsque ce qui suit est exécuté, le module json de python (inclus depuis 2.6) convertit les clés du dictionnaire int en chaînes.
>>> import json
>>> releases = {1: "foo-v0.1"}
>>> json.dumps(releases)
'{"1": "foo-v0.1"}'
Existe-t-il un moyen simple de conserver la clé en tant qu'int, sans avoir besoin d'analyser la chaîne lors du vidage et du chargement. Je pense qu'il serait possible d'utiliser les hooks fournis par le module json, mais encore une fois, cela nécessite toujours une analyse. Y a-t-il peut-être un argument que j'ai négligé? bravo, chaz
Sous-question: Merci pour les réponses. Vu que json fonctionne comme je le craignais, y a-t-il un moyen facile de transmettre le type de clé en analysant peut-être la sortie des vidages? Je dois également noter que le code faisant le dumping et le code téléchargeant l'objet json à partir d'un serveur et le chargeant, sont tous deux écrits par moi.
Réponses:
C'est l'une de ces différences subtiles entre les différentes collections de cartographie qui peuvent vous mordre. JSON traite les clés comme des chaînes; Python prend en charge des clés distinctes ne différant que par le type.
En Python (et apparemment en Lua), les clés d'un mappage (dictionnaire ou table, respectivement) sont des références d'objet. En Python, ils doivent être des types immuables ou des objets qui implémentent une
__hash__
méthode. (La documentation Lua suggère qu'il utilise automatiquement l'ID de l'objet comme un hachage / clé même pour les objets mutables et s'appuie sur l'internalisation de chaînes pour garantir que les chaînes équivalentes correspondent aux mêmes objets).En Perl, Javascript, awk et de nombreux autres langages, les clés pour les hachages, les tableaux associatifs ou tout ce qu'ils appellent pour le langage donné, sont des chaînes (ou "scalaires" en Perl). En perl se
$foo{1}, $foo{1.0}, and $foo{"1"}
trouvent toutes les références au même mappage en%foo
--- la clé est évaluée comme un scalaire!JSON a commencé comme une technologie de sérialisation Javascript. (JSON signifie J ava S cript O bjet N ottaison.) Bien entendu , il met en oeuvre la sémantique pour sa notation de correspondance qui sont compatibles avec la sémantique de mappage.
Si les deux extrémités de votre sérialisation doivent être Python, vous feriez mieux d'utiliser des pickles. Si vous avez vraiment besoin de les reconvertir de JSON en objets Python natifs, je suppose que vous avez plusieurs choix. Vous pouvez d'abord essayer (
try: ... except: ...
) de convertir n'importe quelle clé en nombre en cas d'échec de la recherche dans le dictionnaire. Sinon, si vous ajoutez du code à l'autre extrémité (le sérialiseur ou le générateur de ces données JSON), vous pouvez lui demander d'effectuer une sérialisation JSON sur chacune des valeurs de clé - en les fournissant sous forme de liste de clés. (Ensuite, votre code Python itérerait d'abord sur la liste des clés, les instanciant / désérialisant en objets Python natifs ... puis les utiliserait pour accéder aux valeurs hors du mappage).la source
Non, il n'existe pas de clé numérique en JavaScript. Toutes les propriétés d'objet sont converties en String.
Cela peut conduire à des comportements d'apparence curieuse:
Les objets JavaScript ne sont pas vraiment des mappages appropriés comme vous le comprenez dans des langages comme Python, et l'utilisation de clés qui ne sont pas String entraîne des bizarreries. C'est pourquoi JSON écrit toujours explicitement les clés sous forme de chaînes, même là où cela ne semble pas nécessaire.
la source
999999999999999999999
converti en'999999999999999999999'
?Number
type est une valeur à double virgule flottante IEEE 754 : vous obtenez 53 bits de mantisse, vous pouvez donc stocker jusqu'à 2⁵³ (9007199254740992) avec une précision entière; au-delà, les entiers arrondiront à d'autres valeurs (d'où 9007199254740993 === 9007199254740992). 999999999999999999999 est arrondi à 1000000000000000000000, pour lequel latoString
représentation par défaut est1e+21
.Vous pouvez également essayer de convertir le dictionnaire en une liste au format [(k1, v1), (k2, v2)] tout en l'encodant à l'aide de json, et en le reconvertissant en dictionnaire après l'avoir décodé.
Je pense que cela nécessitera plus de travail, comme avoir une sorte de drapeau pour identifier tous les paramètres à convertir en dictionnaire après l'avoir décodé à partir de json.la source
Répondre à votre sous-question:
Cela peut être accompli en utilisant
json.loads(jsonDict, object_hook=jsonKeys2int)
Cette fonction fonctionnera également pour les dictionnaires imbriqués et utilise une compréhension de dict.
Si vous souhaitez également convertir les valeurs, utilisez:
Qui teste l'instance des valeurs et ne les casse que s'il s'agit d'objets chaînes (unicode pour être exact).
Les deux fonctions supposent que les clés (et les valeurs) sont des entiers.
Grâce à:
Comment utiliser if / else dans une compréhension de dictionnaire?
Convertir une clé de chaîne en int dans un dictionnaire
la source
J'ai été mordu par le même problème. Comme d'autres l'ont souligné, dans JSON, les clés de mappage doivent être des chaînes. Vous pouvez faire deux choses. Vous pouvez utiliser une bibliothèque JSON moins stricte, comme demjson , qui autorise les chaînes entières. Si aucun autre programme (ou aucun autre dans d'autres langues) ne va le lire, alors vous devriez être d'accord. Ou vous pouvez utiliser un autre langage de sérialisation. Je ne suggérerais pas de cornichon. Il est difficile à lire et n'est pas conçu pour être sécurisé . Au lieu de cela, je suggérerais YAML, qui est (presque) un sur-ensemble de JSON, et autorise les clés entières. (Au moins PyYAML le fait.)
la source
Convertissez le dictionnaire en chaîne en utilisant
str(dict)
, puis reconvertissez-le en dict en procédant comme suit:la source
Voici ma solution! Je l'ai utilisé
object_hook
, c'est utile quand on a imbriquéjson
Il existe un filtre uniquement pour analyser la clé json en int. Vous pouvez également utiliser un
int(v) if v.lstrip('-').isdigit() else v
filtre pour la valeur json.la source
J'ai fait une extension très simple de la réponse de Murmel qui, je pense, fonctionnera sur un dictionnaire assez arbitraire (y compris imbriqué) en supposant qu'il puisse être vidé par JSON en premier lieu. Toutes les clés qui peuvent être interprétées comme des entiers seront converties en int. Il ne fait aucun doute que ce n'est pas très efficace, mais cela fonctionne pour mes besoins de stockage et de chargement à partir de chaînes json.
En supposant que toutes les clés du dict original sont des entiers si elles peuvent être transtypées en int, cela renverra le dictionnaire d'origine après le stockage en tant que json. par exemple
la source
Vous pouvez écrire vous-
json.dumps
même, voici un exemple de djson : encoder.py . Vous pouvez l'utiliser comme ceci:la source