For serializing Python objects to JSON and back
Project description
|PyPI version| |Docs| |Build Status| |Scrutinizer Code Quality| |Maintainability|
jsons
A Python (3.5+) lib for deeply serializing Python objects to dicts or strings and for deserializing dicts or strings to Python objects using type hints.
With jsons
, you can serialize/deserialize most objects already. You
can also easily extend jsons
yourself by defining a custom
serializer/deserializer for a certain type. Furthermore, any default
serializer/deserializer can be overridden. Some
serializers/deserializers accept extra parameters to allow you to tune
the serialization/deserialization process to your need.
jsons
generates human-readable dicts or JSON strings that are not
polluted with metadata.
Why not use __dict__
for serialization?
'''''''''''''''''''''''''''''''''''''''''''
- The
__dict__
attribute only creates a shallow dict of an instance. Any contained object is not serialized to a dict. - The
__dict__
does not take@property
methods in account. - Not all objects have a
__dict__
attribute (e.g.datetime
does not). - The serialization process of
__dict__
cannot easily be tuned. - There is no means to deserialize with
__dict__
.
Installation ''''''''''''
::
pip install jsons
Usage '''''
.. code:: python
import jsons
some_instance = jsons.load(some_dict, SomeClass) # Deserialization some_dict = jsons.dump(some_instance) # Serialization
API overview ''''''''''''
dump(obj: object) -> dict
: serializes an object to a dict.load(json_obj: dict, cls: type = None) -> object
: deserializes a dict to an object of typecls
.dumps(obj: object, *args, **kwargs) -> str
: serializes an object to a string.loads(s: str, cls: type = None, *args, **kwargs) -> object
deserializes a string to an object of typecls
.set_serializer(c: callable, cls: type) -> None
: sets a custom serialization function for typecls
.set_deserializer(c: callable, cls: type) -> None
: sets a custom deserialization function for typecls
.JsonSerializable
: a base class that allows for convenient use of the jsons features.
Examples ''''''''
Example with dataclasses
.. code:: python
from dataclasses import dataclass from typing import List import jsons
You can use dataclasses (since Python3.7). Regular Python classes
(Python3.5+) will work as well as long as type hints are present for
custom classes.
@dataclass class Student: name: str
@dataclass class ClassRoom: students: List[Student]
c = ClassRoom([Student('John'), Student('Mary'), Student('Greg'), Student('Susan')]) dumped_c = jsons.dump(c) print(dumped_c)
Prints:
{'students': [{'name': 'John'}, {'name': 'Mary'},
{'name': 'Greg'}, {'name': 'Susan'}]}
loaded_c = jsons.load(dumped_c, ClassRoom) print(loaded_c)
Prints:
ClassRoom(students=[Student(name='John'), Student(name='Mary'),
Student(name='Greg'), Student(name='Susan')])
Example with regular classes
.. code:: python
from typing import List import jsons
class Student:
# Since name
is expected to be a string, no type hint is required.
def init(self, name):
self.name = name
class ClassRoom:
# Since Student
is a custom class, a type hint must be given.
def init(self, students: List[Student]):
self.students = students
c = ClassRoom([Student('John'), Student('Mary'), Student('Greg'), Student('Susan')]) dumped_c = jsons.dump(c) print(dumped_c)
Prints:
{'students': [{'name': 'John'}, {'name': 'Mary'},
{'name': 'Greg'}, {'name': 'Susan'}]}
loaded_c = jsons.load(dumped_c, ClassRoom) print(loaded_c)
Prints:
<main.ClassRoom object at 0x0337F9B0>
Example with JsonSerializable
.. code:: python
from jsons import JsonSerializable
class Car(JsonSerializable): def init(self, color): self.color = color
c = Car('red') cj = c.json # You can also do 'c.dump(**kwargs)' print(cj)
Prints:
{'color': 'red'}
c2 = Car.from_json(cj) # You can also do 'Car.load(cj, **kwargs)' print(c2.color)
Prints:
'red'
Advanced features '''''''''''''''''
Overriding the default (de)serialization behavior
You may alter the behavior of the serialization and deserialization processes yourself by defining your own custom serialization/deserialization functions.
.. code:: python
jsons.set_serializer(custom_serializer, datetime) # A custom datetime serializer. jsons.set_deserializer(custom_deserializer, str) # A custom string deserializer.
A custom serializer must have the following form:
.. code:: python
def someclass_serializer(obj: SomeClass, **kwargs) -> dict: # obj is the instance that needs to be serialized. # Make sure to return a type with a JSON equivalent, one of: # (str, int, float, bool, list, dict, None) return obj.dict
A custom deserializer must have the following form:
.. code:: python
def someclass_serializer(obj: object, cls: type = None, **kwargs) -> object: # obj is the instance that needs to be deserialized. # cls is the type that is to be returned. In most cases, this is the # type of the object before it was serialized. return SomeClass(some_arg=obj['some_arg'])
Note that in both cases, if you choose to call any other (de)serializer within
your own, you should also pass the **kwargs
upon calling.
Transforming the JSON keys
You can have the keys transformed by the serialization or deserialization process by providing a transformer function that takes a string and returns a string.
.. code:: python
result = jsons.dump(some_obj, key_transformer=jsons.KEY_TRANSFORMER_CAMELCASE)
result could be something like: {'thisIsTransformed': 123}
result = jsons.load(some_dict, SomeClass, key_transformer=jsons.KEY_TRANSFORMER_SNAKECASE)
result could be something like: {'this_is_transformed': 123}
The following casing styles are supported:
.. code:: python
KEY_TRANSFORMER_SNAKECASE # snake_case KEY_TRANSFORMER_CAMELCASE # camelCase KEY_TRANSFORMER_PASCALCASE # PascalCase KEY_TRANSFORMER_LISPCASE # lisp-case
Customizing JsonSerializable
You can customize the behavior of the JsonSerializable
class or extract a
new class from it. This can be useful if you are using jsons
extensively
throughout your project, especially if you wish to have different
(de)serialization styles in different occasions.
.. code:: python
forked = JsonSerializable.fork() forked.set_serializer(custom_serializer, datetime) # A custom serializer.
class Person(forked): def init(self, dt: datetime): self.dt = dt
p = Person('John') p.json # Will contain a serialized dt using 'custom_serializer'.
jsons.dump(datetime.now()) # Still uses the default datetime serializer.
In the above example, a custom serializer is set to a fork of
JsonSerializable
. The regular jsons.dump
does not have this custom
serializer and will therefore behave as it used to.
You can also create a fork of a fork. All serializers and deserializers of the type that was forked, are copied.
You can also define default kwargs
which are then automatically passed as
arguments to the serializing and deserializing methods (dump
, load
,
...). You can use with_dump
and with_load
to set default kwargs
to
the serialization and deserialization process respectively.
.. code:: python
custom_serializable = JsonSerializable
.with_dump(key_transformer=KEY_TRANSFORMER_CAMELCASE)
.with_load(key_transformer=KEY_TRANSFORMER_SNAKECASE)
class Person(custom_serializable): def init(self, my_name): self.my_name = my_name
p = Person('John') p.json # {'myName': 'John'} <-- note the camelCase
p2 = Person.from_json({'myName': 'Mary'}) p2.my_name # 'Mary' <-- note the snake_case in my_name
You can, of course, also do this with a fork of JsonSerializable
or you
can create a fork in the process by setting fork=True
in with_dump
or
with_load
.
.. |PyPI version| image:: https://badge.fury.io/py/jsons.svg :target: https://badge.fury.io/py/jsons
.. |Docs| image:: https://readthedocs.org/projects/jsons/badge/?version=latest :target: https://jsons.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status
.. |Build Status| image:: https://travis-ci.org/ramonhagenaars/geomodels.svg?branch=master :target: https://travis-ci.org/ramonhagenaars/jsons .. |Scrutinizer Code Quality| image:: https://scrutinizer-ci.com/g/ramonhagenaars/jsons/badges/quality-score.png?b=master :target: https://scrutinizer-ci.com/g/ramonhagenaars/jsons/?branch=master .. |Maintainability| image:: https://api.codeclimate.com/v1/badges/17d997068b3387c2f2c3/maintainability :target: https://codeclimate.com/github/ramonhagenaars/jsons/maintainability
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.