J'ai une liste de dict sous la forme suivante que je génère à partir de pandas. Je veux le convertir au format json.
list_val = [{1.0: 685}, {2.0: 8}]
output = json.dumps(list_val)
Cependant, json.dumps génère une erreur: TypeError: 685 n'est pas sérialisable JSON
Je suppose que c'est un problème de conversion de type de numpy en python (?).
Cependant, lorsque je convertis les valeurs v de chaque dict du tableau à l'aide de np.int32 (v), il renvoie toujours l'erreur.
EDIT: Voici le code complet
new = df[df[label] == label_new]
ks_dict = json.loads(content)
ks_list = ks_dict['variables']
freq_counts = []
for ks_var in ks_list:
freq_var = dict()
freq_var["name"] = ks_var["name"]
ks_series = new[ks_var["name"]]
temp_df = ks_series.value_counts().to_dict()
freq_var["new"] = [{u: np.int32(v)} for (u, v) in temp_df.iteritems()]
freq_counts.append(freq_var)
out = json.dumps(freq_counts)
Il semble que vous ayez raison:
>>> import numpy
>>> import json
>>> json.dumps(numpy.int32(685))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/json/encoder.py", line 184, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: 685 is not JSON serializable
La chose malheureuse ici est que les nombres numpy '__repr__
ne vous donne aucune indication sur le type qu'ils sont. Ils courent en se faisant passer pour int
s quand ils ne le sont pas ( halètement ). En fin de compte, il semble que json
vous indique qu'un int
n'est pas sérialisable, mais vraiment, il vous dit que ce np.int32 particulier (ou tout autre type que vous avez réellement) ne l'est pas sérialisable. (Pas de vraie surprise là-bas - Aucun np.int32 n'est sérialisable). C'est aussi pourquoi le dict que vous avez inévitablement imprimé avant de le passer à json.dumps
on dirait qu'il contient aussi des entiers.
La solution de contournement la plus simple ici est probablement de écrire votre propre sérialiseur1:
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, numpy.integer):
return int(obj)
Elif isinstance(obj, numpy.floating):
return float(obj)
Elif isinstance(obj, numpy.ndarray):
return obj.tolist()
else:
return super(MyEncoder, self).default(obj)
Vous l'utilisez comme ceci:
json.dumps(numpy.float32(1.2), cls=MyEncoder)
json.dumps(numpy.arange(12), cls=MyEncoder)
json.dumps({'a': numpy.int32(42)}, cls=MyEncoder)
etc.
1Ou vous pouvez simplement écrire la fonction par défaut et la passer comme argument de mot clé defaut
à json.dumps
. Dans ce scénario, vous remplaceriez la dernière ligne par raise TypeError
, mais ... meh. La classe est plus extensible :-)
Vous pouvez également convertir le tableau en une liste python (utilisez la méthode tolist
)), puis convertir la liste en json.
Si vous laissez les données dans l'un des objets pandas
, la bibliothèque fournit un to_json
fonctionne sur Series, DataFrame et tous les autres cousins de dimension supérieure.
Voir Series.to_json ()
Vous pouvez utiliser notre fork d'ujson pour gérer NumPy int64. caiyunapp/ultrajson: décodeur et encodeur JSON ultra rapide écrit en C avec Python et liaisons NumPy
pip install nujson
Ensuite
>>> import numpy as np
>>> import nujson as ujson
>>> a = {"a": np.int64(100)}
>>> ujson.dumps(a)
'{"a":100}'
>>> a["b"] = np.float64(10.9)
>>> ujson.dumps(a)
'{"a":100,"b":10.9}'
>>> a["c"] = np.str_("12")
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12"}'
>>> a["d"] = np.array(list(range(10)))
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12","d":[0,1,2,3,4,5,6,7,8,9]}'
>>> a["e"] = np.repeat(3.9, 4)
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12","d":[0,1,2,3,4,5,6,7,8,9],"e":[3.9,3.9,3.9,3.9]}'