Je suis encore un peu nouveau à ce sujet, donc je ne connais peut-être pas tous les termes conventionnels des choses:
Est-il possible de conserver Python tuples lors de l'encodage avec JSON? Pour l'instant, json.loads(json.dumps(Tuple))
me donne une liste. Je ne veux pas convertir mes tuples en listes, mais je voulez utiliser JSON. Alors, y a-t-il des options?
La raison pour laquelle: je crée une application qui utilise des tableaux multidimensionnels, pas toujours de la même forme. J'ai quelques méthodes de classe qui utilisent la récursivité pour sonder les tableaux et convertir les points de terminaison en chaîne ou en entier. J'ai récemment réalisé que (sur la base du fonctionnement de ma récursivité), je peux utiliser des tuples pour empêcher une recherche récursive plus approfondie des tableaux (Python rawks). Cela pourrait être utile dans des situations où je sais que je n'aurai certainement pas besoin d'approfondir mes structures de données.
Vous pouvez écrire un encodeur hautement spécialisé et un crochet de décodeur:
import json
class MultiDimensionalArrayEncoder(json.JSONEncoder):
def encode(self, obj):
def hint_tuples(item):
if isinstance(item, Tuple):
return {'__Tuple__': True, 'items': item}
if isinstance(item, list):
return [hint_tuples(e) for e in item]
if isinstance(item, dict):
return {key: hint_tuples(value) for key, value in item.items()}
else:
return item
return super(MultiDimensionalArrayEncoder, self).encode(hint_tuples(obj))
def hinted_Tuple_hook(obj):
if '__Tuple__' in obj:
return Tuple(obj['items'])
else:
return obj
enc = MultiDimensionalArrayEncoder()
jsonstring = enc.encode([1, 2, (3, 4), [5, 6, (7, 8)]])
print jsonstring
# [1, 2, {"items": [3, 4], "__Tuple__": true}, [5, 6, {"items": [7, 8], "__Tuple__": true}]]
print json.loads(jsonstring, object_hook=hinted_Tuple_hook)
# [1, 2, (3, 4), [5, 6, (7, 8)]]
Non, ce n'est pas possible. Il n'y a pas de concept de Tuple au format JSON (voir ici pour une ventilation concise des types existants dans JSON). Le module json
de Python convertit Python en listes JSON car c'est ce qui se rapproche le plus en JSON d'un Tuple.
Vous n'avez pas donné beaucoup de détails sur votre cas d'utilisation ici, mais si vous avez besoin de stocker des représentations de chaînes de structures de données qui incluent des tuples, quelques possibilités viennent immédiatement à l'esprit, qui peuvent ou non être appropriées selon votre situation:
pickle.loads
n'est pas sûr à utiliser sur les entrées fournies par l'utilisateur).repr
et ast.literal_eval
au lieu de json.dumps
et json.loads
. repr
vous donnera une sortie d'aspect raisonnablement similaire à json.dumps
, mais repr
ne convertira pas les tuples en listes. ast.literal_eval
est une version moins puissante et plus sécurisée de eval
qui décode uniquement les chaînes, les nombres, les tuples, les listes, les dict, les booléens et None
.L'option 3 est probablement la solution la plus simple et la plus simple pour vous.
La principale différence entre python listes et tuples est la mutabilité, qui n'est pas pertinente pour les représentations JSON, tant que vous n'envisagez pas de modifier les membres internes de la liste JSON lorsqu'elle est sous forme de texte. Vous peut simplement transformer les listes que vous obtenez en tuples. Si vous n'utilisez pas de décodeurs d'objets personnalisés, les seuls types de données structurés que vous devez prendre en compte sont les objets et les tableaux JSON, qui se présentent sous la forme python dits et listes.
def tuplify(listything):
if isinstance(listything, list): return Tuple(map(tuplify, listything))
if isinstance(listything, dict): return {k:tuplify(v) for k,v in listything.items()}
return listything
Si vous spécialisez le décodage ou si vous voulez que certains tableaux JSON soient python listes et d'autres python tuples, vous devrez encapsuler les éléments de données dans un dict ou un tuple qui annote les informations de type. C'est en soi un meilleur moyen d'influencer le flux de contrôle d'un algorithme que la ramification selon que quelque chose est une liste ou un tuple (ou un autre type itérable).
C'est avec simplejson
import simplejson
def _to_json(python_object) :
if isinstance(python_object, Tuple) :
python_object = {'__class__': 'Tuple',
'__value__': list(python_object)}
else :
raise TypeError(repr(python_object) + ' is not JSON serializable')
return python_object
def _from_json(json_object):
if json_object['__class__'] == 'Tuple':
return Tuple(json_object['__value__'])
return json_object
jsn = simplejson.dumps((1,2,3),
default=_to_json,
Tuple_as_array=False)
tpl = simplejson.loads(jsn, object_hook=_from_json)