How to Resolve "TypeError: Object of type numpy.int64/float32 is not JSON serializable" in Python
When working with NumPy arrays, you might encounter TypeError: Object of type int64 is not JSON serializable
or TypeError: Object of type float32 is not JSON serializable
. These errors occur because Python's standard json
module doesn't natively recognize NumPy's specific numeric types.
This guide explains why this happens and provides several practical solutions for successful JSON serialization.
Understanding the Error: JSON and NumPy Types
JSON (JavaScript Object Notation) is a text-based format with a limited set of data types (strings, numbers, booleans, arrays, objects, null). Python's json.dumps()
function can serialize standard Python types like int
, float
, str
, list
, dict
, bool
, and None
.
However, NumPy introduces its own, more specialized numeric types (like numpy.int64
, numpy.float32
) to handle large datasets and optimize performance. These NumPy-specific types are not directly recognized by the default JSON encoder.
import json
import numpy as np
# Example causing int64 TypeError
salary_int = np.int64(100000000)
# json_str = json.dumps({'salary': salary_int}) # ⛔️ TypeError
# Example causing float32 TypeError
salary_float = np.float32(316227.78)
# json_str = json.dumps({'salary': salary_float}) # ⛔️ TypeError
Solution 1: Convert NumPy Types to Python Primitives (Recommended)
The simplest and often most effective solution is to explicitly convert the NumPy numeric types to their standard Python equivalents (int
or float
) before serialization:
Converting NumPy Integers (np.int64
, np.int32
, etc.)
Use the built-in int()
constructor:
import json
import numpy as np
salary_int = np.int64(100000000)
# Convert NumPy int to Python int
json_str = json.dumps({'salary': int(salary_int)})
print(json_str) # Output: {"salary": 100000000}
print(type(json_str)) # Output: <class 'str'>
Converting NumPy Floats (np.float32
, np.float64
, etc.)
Use the built-in float()
constructor:
import json
import numpy as np
salary_float = np.float32(316227.78)
# Convert NumPy float to Python float
json_str = json.dumps({'salary': float(salary_float)})
print(json_str) # Output: {"salary": 316227.78125}
print(type(json_str)) # Output: <class 'str'>
Converting np.float32
to a standard Python float
(which is typically 64-bit) might slightly alter the precision, as seen in the output (.78
becomes .78125
).
If exact string representation is critical, convert to string using str()
instead: json.dumps({'salary': str(salary_float)})
. However, the receiving system would then need to parse the string back to a number.
Solution 2: Create a Custom NumPy JSON Encoder
For situations where you frequently serialize data containing various NumPy types, creating a custom JSONEncoder
subclass is a clean and reusable approach:
import json
import numpy as np
class NpEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj) # Convert NumPy int to Python int
elif isinstance(obj, np.floating):
return float(obj) # Convert NumPy float to Python float
elif isinstance(obj, np.ndarray):
return obj.tolist() # Convert NumPy array to Python list
return super().default(obj) # Let the base class handle the rest
# Example Usage
data_to_serialize = {
'count': np.int32(5),
'average': np.float64(12.345),
'values': np.array([1, 2, 3])
}
json_str = json.dumps(data_to_serialize, cls=NpEncoder)
print(json_str)
# Output: {"count": 5, "average": 12.345, "values": [1, 2, 3]}
- This custom encoder handles common NumPy integers, floats, and arrays.
- You pass the custom encoder class to the
cls
argument ofjson.dumps()
.
Solution 3: Use the default
Argument in json.dumps()
A simpler alternative to a full class is providing a function to the default
argument of json.dumps()
. This function handles types the standard encoder doesn't recognize:
import json
import numpy as np
def numpy_serializer(obj):
if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
np.int16, np.int32, np.int64, np.uint8,
np.uint16, np.uint32, np.uint64)):
return int(obj)
elif isinstance(obj, (np.float_, np.float16, np.float32, np.float64)):
return float(obj)
elif isinstance(obj, np.ndarray):
return obj.tolist()
# Let the default encoder raise the TypeError for other types
raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
# Example Usage
data_to_serialize = {
'count': np.int32(5),
'average': np.float64(12.345),
}
json_str = json.dumps(data_to_serialize, default=numpy_serializer)
print(json_str) # Output: {"count": 5, "average": 12.345}
- The
numpy_serializer
function checks the type and performs the necessary conversion. - Explicitly raising a
TypeError
for unhandled types in thedefault
function is good practice.
Conclusion
The TypeError
related to NumPy int64
or float32
not being JSON serializable stems from the standard json
module's inability to handle these specific numeric types.
The most straightforward solution is to explicitly convert NumPy numbers to standard Python int
or float
types before serialization.
For more complex or frequent scenarios, creating a custom JSONEncoder
or using the default
argument provides reusable and cleaner ways to handle various NumPy types during JSON conversion.