pyobjson - Python Object JSON Tool¶
Utility library for serializing/deserializing custom Python objects to/from JSON.
Do you like the Python Object JSON Tool? Star the repository on GitHub and please consider helping support its ongoing development:
READ THE DOCS HERE!
Detailed documentation can be found at https://pyobjson.wrencode.dev.
Table of Contents¶
About¶
The Python Object JSON Tool is a utility library for serializing/deserializing custom Python objects to/from JSON by
using pyobjson
classes as superclasses/parent classes to your custom Python classes.
Installation¶
You can install with pip
by running:
pip install pyobjson
Note: If you wish to use pyobjson
to serialize/deserialize custom Python objects to/from MongoDB, then you have
to install with the optional dependencies:
pip install pyobjson[mongo]
Dependencies¶
The base Python Object JSON Tool does not have any third-party dependencies to run the code. It has several development
dependencies, which can be seen in the package pyproject.toml
.
If you wish to use pyobjson
to serialize/deserialize custom Python objects to/from MongoDB, then there is an
additional dependency on the PyMongo package.
Toolchain¶
The below tools and resources are used as part of pyobjson:
- uv - package management
- ruff - code linting
- bandit - code security
- make - Makefile build automation
- MkDocs - package documentation
- python-dotenv - programmatic access to environment variables defined in
a
.env
file - pytest - code testing framework
- GitHub Actions - CI/CD
- act - GitHub Actions testing
Usage¶
The pyobjson
package is designed to be used as a base class/parent class/superclass to your own custom Python classes
in order to provide built-in, convenient serialization/deserialization functionality. Child classes/subclasses of
pyobjson.base.PythonObjectJson
will automatically have the following methods:
pyobjson.base.PythonObjectJson.serialize()
: Create a serializable dictionary from the class instance.pyobjson.base.PythonObjectJson.to_json_str()
: Serialize the class instance to a JSON string.pyobjson.base.PythonObjectJson.from_json_str(json_str)
: Load the class instance from apyobjson
-formatted JSON string.pyobjson.base.PythonObjectJson.save_to_json_file(json_file_path)
: Save the class instance to a JSON file.pyobjson.base.PythonObjectJson.load_from_json_file(json_file_path)
: Load the class instance from apyobjson
-formatted JSON file.
Please reference the documentation at https://pyobjson.wrencode.dev for more detailed usage.
JSON Example¶
from pyobjson.base import PythonObjectJson
class MyOtherClass(PythonObjectJson):
def __init__(self):
super().__init__()
self.message = "Hello, World!"
class MyClass(PythonObjectJson):
def __init__(self):
super().__init__()
self.my_other_classes = [MyOtherClass()]
my_class = MyClass()
print(my_class.to_json_str())
JSON Example Output¶
{
"__main__.myclass": {
"collection::::list::::my_other_classes": [
{
"__main__.myotherclass": {
"message": "Hello, World!"
}
}
]
}
}
The above example shows how pyobjson
can be used to serialize arbitrary custom Python classes into JSON. Additionally,
the above JSON example output JSON can be used to recreate an equivalent class instance by
loading the JSON into a custom Python class instance.
Saving and Loading¶
The pyobjson.base.PythonObjectJson
parent class also provides built-in methods to save/load arbitrary custom Python
classes to/from JSON in several ways.
JSON Files¶
- JSON files (using only Python built-in libraries): Use the
PythonObjectJson.save_to_json_file(json_file_path)
andPythonObjectJson.load_from_json_file(json_file_path)
methods to save/load your custom Python subclasses to JSON files.
JSON File Example¶
from pathlib import Path
from dotenv import load_dotenv
from pyobjson.base import PythonObjectJson
root_dir = Path(__file__).parent
load_dotenv(root_dir / ".env")
class CustomClassToJsonFile(PythonObjectJson):
def __init__(self, message: str):
super().__init__()
self.message = message
custom_class_to_json_file = CustomClassToJsonFile("Hello, World!")
output_dir = root_dir / "output"
if not output_dir.is_dir():
output_dir.mkdir(parents=True, exist_ok=True)
custom_class_to_json_file.save_to_json_file(output_dir / "custom_class_to_json_file.json")
custom_class_to_json_file.load_from_json_file(output_dir / "custom_class_to_json_file.json")
JSON File Output¶
{
"__main__.customclasstojsonfile": {
"message": "Hello, World!"
}
}
MongoDB¶
- MongoDB (using
pymongo
): Thepyobjson
library includes a class calledpyobjson.dao.PythonObjectJsonToMongo
, which can be used as a superclass for any custom class you wish to be able to easily serialized/deserialize to/from MongoDB. Use thePythonObjectJsonToMongo.save_to_mongo(mongo_collection)
andPythonObjectJsonToMongo.load_from_mongo(mongo_collection, document_id)
methods to save/load your custom Python subclasses to MongoDB.
MongoDB Example¶
import os
from pathlib import Path
from dotenv import load_dotenv
from pyobjson.dao.mongo.base import PythonObjectJsonToMongo
load_dotenv(Path(__file__).parent / ".env")
class CustomClassToMongo(PythonObjectJsonToMongo):
def __init__(self, mongo_host: str, mongo_port: int, mongo_database: str, mongo_user: str, mongo_password: str):
super().__init__(mongo_host, mongo_port, mongo_database, mongo_user, mongo_password)
self.message = "Hello, World!"
custom_class_to_mongo = CustomClassToMongo(
mongo_host=os.environ.get("MONGO_HOST"),
mongo_port=int(os.environ.get("MONGO_PORT")),
mongo_database=os.environ.get("MONGO_DATABASE"),
mongo_user=os.environ.get("MONGO_ADMIN_USER"),
mongo_password=os.environ.get("MONGO_ADMIN_PASS"),
)
saved_mongo_document_id = custom_class_to_mongo.save_to_mongo(os.environ.get("MONGO_COLLECTION"))
custom_class_to_mongo.load_from_mongo(os.environ.get("MONGO_COLLECTION"), saved_mongo_document_id)
MongoDB Output¶
print(custom_class_to_mongo)
:
{
"__main__.customclasstomongo": {
"message": "Hello, World!"
}
}
print(repr(custom_class_to_mongo))
:
__main__.CustomClassToMongo(mongo_host=localhost,mongo_port=27017,mongo_database=pyobjson,mongo_user=<mongodb_user>,mongo_password=<mongodb_password>)
Custom Subclasses¶
The PythonObjectJson
base class in pyobjson
is designed to be extended using your own custom subclasses. The
built-in PythonObjectJsonToMongo
class is an example of this functionality, but it can be adapted to work for
additional use cases as well.
Serialization¶
If you have a custom class with attributes that contain data you wish to exclude from the pyobjson
serialized output (
anything from sensitive data like credentials to objects that are not compatible with pyobjson
), you can provide a
list of attribute names (or a list of valid regular expressions) to the excluded_attributes
parameter in the
PythonObjectJson.__init__(...)
, and pyobjson
will automatically exclude any attributes that match those provided
during serialization.
If you only provide values for excluded_attributes
, then pyobjson
will exclude those attributes from all custom
classes being serialized within the root custom class. However, you can also provide a list of class identifiers (like
pyobjson.dao.mongo.base.pythonobjectjsontomongo
to the class_keys_for_excluded_attributes
parameter in the
PythonObjectJson.__init__(...)
, as derived using the pyobjson.utils.derive_custom_object_key
function), in which
case pyobjson
will only exclude the provided excluded_attributes
from the classes in
class_keys_for_excluded_attributes
.
Deserialization¶
Similar to the approach for custom subclass serialization, if you have a custom class with extra
attributes you wish to include during deserialization, you can provide a list of attribute names (or a list of valid
regular expressions) to the extra_attributes
parameters in the PythonObjectJson.__init__(...)
, and pyobjson
will
attempt to re-apply those attributes during deserialization by pulling the values for those extra attributes from the
custom class instance onto which you are deserializing data.
If you only provide values for extra_attributes
, then pyobjson
will attempt to add those attributes to all
custom classes being deserialized onto the root custom class. However, you can also provide a list of class
identifiers (like pyobjson.dao.mongo.base.pythonobjectjsontomongo
to the class_keys_for_extra_attributes
parameter
in the PythonObjectJson.__init__(...)
, as derived using the pyobjson.utils.derive_custom_object_key
function), in
which case pyobjson
will only attempt to add the provided extra_attributes
to the classes in
class_keys_for_extra_attributes
.