web-dev-qa-db-fra.com

Pourquoi les clés int d'un dict Python se transforment-elles en chaînes lors de l'utilisation de json.dumps?

Selon cette table de conversion , les entrées Python sont écrites sous forme de nombres JSON lorsqu’elles sont sérialisées à l’aide du module JSON - comme je l’attendais et le souhaite.

J'ai un dictionnaire avec une clé entière et une valeur entière:

>>> d = {1:2}
>>> type(d.items()[0][0])
<type 'int'>
>>> type(d.items()[0][1])
<type 'int'>

Lorsque j'utilise le module json pour sérialiser cela en une chaîne JSON, la valeur est écrite sous forme de nombre, mais la clé est écrite sous forme de chaîne:

>>> json.dumps(d)
'{"1": 2}'

Ce n'est pas le comportement que je veux, et il semble particulièrement cassé puisqu'il bloque json.dumps/json.loads aller-retour:

>>> d == json.loads(json.dumps(d))
False

Pourquoi cela se produit-il et y a-t-il un moyen de forcer l'écriture de la clé sous forme de nombre?

28
jveldridge

La raison simple est que JSON n'autorise pas les clés entières.

object
    {}
    { members } 
members
    pair
    pair , members
pair
    string : value  # Keys *must* be strings.

Pour contourner cette limitation, vous devez d'abord vous assurer que l'implémentation de réception peut gérer le JSON techniquement non valide. Vous pouvez ensuite remplacer tous les guillemets ou utiliser un sérialiseur personnalisé.

33
Sean Vieira

Si vous voulez vraiment, vous pouvez vérifier que les clés sont convertibles en entiers en utilisant:

def pythonify(json_data):
    for key, value in json_data.iteritems():
        if isinstance(value, list):
            value = [ pythonify(item) if isinstance(item, dict) else item for item in value ]
        Elif isinstance(value, dict):
            value = pythonify(value)
        try:
            newkey = int(key)
            del json_data[key]
            key = newkey
        except TypeError:
            pass
        json_data[key] = value
    return json_data
0
JLT