Borislav Hadzhiev
Wed Apr 20 2022·3 min read
Photo by Kou Kigamine
The Python "TypeError: Object of type float32 is not JSON serializable" occurs
when we try to convert a numpy float32 object to a JSON string. To solve the
error, convert the numpy float to a Python float before converting it to JSON,
e.g. float(my_numpy_float)
.
Here is an example of how the error occurs.
import json import numpy as np salary = np.power(100, 2.75, dtype=np.float32) # ⛔️ TypeError: Object of type float32 is not JSON serializable json_str = json.dumps({'salary': salary})
We tried passing a numpy float32 object to the json.dumps()
method but the
method doesn't handle numpy floats by default.
To solve the error, use the built-in float()
(or str()
) constructor to
convert the numpy float to a native Python float before serializing it.
import json import numpy as np salary = np.power(100, 2.75, dtype=np.float32) print(salary) # 👉️ 316227.78 # ✅ convert to float json_str = json.dumps({'salary': float(salary)}) print(json_str) # 👉️ '{"salary": 316227.78125}' print(type(json_str)) # 👉️ <class 'str'>
We used the built-in float()
constructor to convert the numpy float32 value to
a native Python float.
str()
constructor to convert the value to a string instead.The default JSON encoder handles float
and str
values, so we can use a
native Python float
instead of a numpy float32 when serializing to JSON.
The json.dumps method converts a Python object to a JSON formatted string.
Alternatively, you can extend from the JSONEncoder
class and handle the
conversions in a default
method.
import json import numpy as np class NpEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, np.integer): return int(obj) if isinstance(obj, np.floating): # 👇️ alternatively use str() return float(obj) if isinstance(obj, np.ndarray): return obj.tolist() return json.JSONEncoder.default(self, obj) salary = np.power(100, 2.75, dtype=np.float32) json_str = json.dumps({'salary': salary}, cls=NpEncoder) print(json_str) # 👉️ {"salary": 316227} print(type(json_str)) # 👉️ <class 'str'>
We extended from the JSONEncoder class.
The JSONEncoder
class supports the following objects and types by default.
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int and float derived Enums | number |
True | true |
False | false |
None | null |
Notice that the JSONEncoder
class doesn't support numpy float32 to JSON
conversion by default.
We can handle this by extending from the class and implementing a default()
method that returns a serializable object.
import json import numpy as np class NpEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, np.integer): return int(obj) if isinstance(obj, np.floating): return float(obj) if isinstance(obj, np.ndarray): return obj.tolist() return json.JSONEncoder.default(self, obj)
If the passed in object is an instance of np.integer
, we convert the object to
a Python int
and return the result.
If the passed in object is an instance of np.floating
, we convert it to a
Python float
and return the result.
str()
constructor instead of float()
if you worry about losing precision.If the object is an instance of np.ndarray
, we convert it to a Python list
and return the result.
In all other cases, we let the base classes' default method do the serialization.
To use a custom JSONEncoder
, specify it with the cls
keyword argument in
your call to the json.dumps()
method.
import json import numpy as np class NpEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, np.integer): return int(obj) if isinstance(obj, np.floating): return float(obj) if isinstance(obj, np.ndarray): return obj.tolist() return json.JSONEncoder.default(self, obj) salary = np.power(100, 2.75, dtype=np.float32) # ✅ pass cls kwarg json_str = json.dumps({'salary': salary}, cls=NpEncoder) print(json_str) # 👉️ {"salary": 316227} print(type(json_str)) # 👉️ <class 'str'>
If you don't provide the cls
kwarg, the default JSONEncoder
is used.