json-tricks: Extended JSON Serialization
json-tricks is a Python library that extends the standard `json` module with extra features like support for comments, preserving dictionary order, and native serialization/deserialization of complex types such as NumPy arrays, Pandas DataFrames/Series, datetime objects, and custom Python classes. It is currently at version 3.17.3 and is actively maintained with regular updates.
Common errors
-
TypeError: Object of type <class 'your_module.CustomClass'> is not JSON serializable
cause You are attempting to serialize a custom Python object that `json-tricks` doesn't know how to handle by default, and you haven't provided custom serialization methods (`__json_encode__`, `__json_decode__`) or enabled metadata storage.fixDefine `__json_encode__(self)` and `__json_decode__(cls, **kwargs)` methods in your custom class. Then, ensure you call `json_tricks.dumps(your_object, store_python_metadata=True)`. -
AttributeError: module 'json_tricks' has no attribute 'numpy'
cause You are trying to access the `numpy` submodule (e.g., `json_tricks.numpy`) in version 3.x or newer of `json-tricks`. This submodule access is deprecated and its functionality is now integrated directly into the main module.fixRemove the `.numpy` (or `.pandas`) from your imports and function calls. Simply use `import json_tricks` and then `json_tricks.dumps` or `json_tricks.loads`. Ensure `numpy` is installed. -
json.JSONDecodeError: Expecting value: line X column Y (char Z)
cause This error typically occurs when you try to load JSON that contains C-style comments (which `json-tricks` supports) using Python's standard `json.loads` or `json.load` function, which does not understand comments.fixUse `json_tricks.loads` (or `json_tricks.load` for files) instead of `json.loads`. `json_tricks` is designed to correctly parse JSON containing comments.
Warnings
- gotcha For `json-tricks` to properly restore complex Python objects (like custom classes, NumPy arrays, Pandas DataFrames, or datetimes) to their original types upon deserialization, you must pass `store_python_metadata=True` to the `json_tricks.dumps` function. Without it, these objects might be loaded as generic lists, dictionaries, or strings.
- breaking Before version 3.x, you might have imported specific submodules like `json_tricks.numpy` or `json_tricks.pandas` to access their enhanced serialization. Since version 3.x, these functionalities are directly integrated into the main `json_tricks` module, making the submodule imports largely obsolete and potentially leading to `AttributeError`.
- gotcha While `json-tricks` supports comments in JSON, standard Python's `json` module does not. If you dump JSON with comments using `json_tricks.dumps(..., allow_comments=True)` and then attempt to load it with `json.loads` or `json.load`, it will raise a `json.JSONDecodeError`.
- gotcha Loading JSON from untrusted sources with `store_python_metadata=True` or custom `extra_obj_hooks` can lead to arbitrary code execution. `json-tricks` can dynamically instantiate objects based on metadata, which is a security risk if malicious data is provided.
Install
-
pip install json-tricks -
pip install json-tricks[numpy,pandas]
Imports
- json_tricks
import json_tricks.numpy
import json_tricks
- dumps
json_tricks.numpy.dumps
json_tricks.dumps
- loads
json.loads
json_tricks.loads
Quickstart
import json_tricks
import numpy as np
import datetime
import pandas as pd
# Example data with extended types
data = {
'numbers': np.array([1, 2, 3]),
'timestamp': datetime.datetime.now(),
'dataframe': pd.DataFrame({'a': [1, 2], 'b': [3, 4]}),
'mixed_list': [1, 'text', {'key': True}],
'comments_example': '// This is a comment inside JSON' # Will be stripped unless allow_comments is used in dump
}
# Dump to a JSON string with metadata to enable full round-tripping
json_string = json_tricks.dumps(data, indent=4, store_python_metadata=True)
print('--- Dumped JSON ---')
print(json_string)
# Load from the JSON string
loaded_data = json_tricks.loads(json_string)
print('\n--- Loaded Data ---')
print(loaded_data)
# Verify types were restored
print(f"Type of 'numbers': {type(loaded_data['numbers'])} ")
print(f"Content of 'numbers': {loaded_data['numbers']}")
print(f"Type of 'timestamp': {type(loaded_data['timestamp'])}")
print(f"Type of 'dataframe': {type(loaded_data['dataframe'])}")