Easily serialize dataclasses to and from JSON
Project description
serious
Python dataclasses serialization and validation.
On top of coupling of data with its behaviour, using proper objects adds semantic meaning to your code. Good classes manifest the intentions of the system and restrictions imposed on it. They make APIs cleaner, changes become simpler to implement, and maintenance becomes cheaper.
Basics
Installation
Available from PyPI:
pip install serious
Quick Example
Central part of Serious API are different Models.
Given a regular dataclass:
from dataclasses import dataclass
@dataclass
class Person:
name: str
Let’s create a JsonModel
:
from serious.json import JsonModel
model = JsonModel(Person)
And use its dump/load methods:
person = Person('Albert Einstein')
model.dump(person) # {"name": "Albert Einstein"}
Validation
To add validation to the example above all we need is to add __validate__
method to person:
from dataclasses import dataclass
from typing import Optional
from serious import ValidationError, Email
@dataclass
class Person:
name: str
email: Optional[Email]
phone: Optional[str]
def __validate__(self):
if len(self.name) == 0:
raise ValidationError('Every person needs a name')
if self.phone is None and self.email is None:
raise ValidationError('At least some contact should be present')
Features
- Model definitions in pure Python.
- Validation showing up in code coverage.
- Type annotations for all public-facing APIs.
- (Optionally) ensures immutability.
- Easily extensible.
- Documented for Humans.
Supported formats:
- JSON
- Python Dictionaries
- YAML
- Form data
Supported field types
- Other dataclasses
- Primitives:
str
,int
,float
,bool
- Dictionaries: only with string keys:
Dict[str, Any]
- Lists, sets, deques: python collections of any serializable type
- Tuples both with and without ellipsis:
- tuples as set of independent elements (e.g.
Tuple[str, int, date]
) - with ellipses, acting as a frozen list (
Tuple[str, ...]
)
- tuples as set of independent elements (e.g.
- Enumerations by value:
- of primitives (e.g.
OperatingSystem(Enum)
) - typed enums (
Color(str, Enum)
andFilePermission(IntFlag)
)
- of primitives (e.g.
- Decimal: encoded to JSON as string
- Datetime, date and time: encoded to the ISO 8601 formatted string
- UUID
serious.types.Timestamp
: a UTC timestamp since UNIX epoch as float ms valueserious.types.Email
: a string Tiny Type that supports validation and contains additional properties- custom immutable alternatives to native python types in
serious.types
:FrozenList
,FrozenDict
A bigger example
from dataclasses import dataclass
from serious import JsonModel, ValidationError
from typing import List
from enum import Enum
class Specialty(Enum):
Worker = 1
Fool = 2
@dataclass(frozen=True)
class Minion:
name: str
type: Specialty
@dataclass(frozen=True)
class Boss:
name: str
minions: List[Minion]
def __validate__(self):
if len(self.minions) < 2:
raise ValidationError('What kind of boss are you?')
boss = Boss("me", [Minion('evil minion', Specialty.Fool), Minion('very evil minion', Specialty.Worker)])
boss_json = """{
"name": "me",
"minions": [
{
"name": "evil minion",
"type": 2
},
{
"name": "very evil minion",
"type": 1
}
]
}"""
model = JsonModel(Boss, indent=4)
assert model.dump(boss) == boss_json
assert model.load(boss_json) == boss
Acknowledgements
Initially, a fork of @lidatong/dataclasses-json.
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.
Source Distribution
Built Distribution
Hashes for serious-1.0.0.dev9-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 523c785e307d42119810832d618139ffabb69f5adbe4a4d6d3e7a19bef87b812 |
|
MD5 | 0204c18a3432deaba413973dacaa8347 |
|
BLAKE2b-256 | 5a648f5112290a4f1041c22479b22eae7c0e06026dedc52f5fcde8d0c44f48ba |