Easily read objects from json
Project description
fromjson
Python library to easily read objects from JSON.
Have you ever had classes, which you want to read from JSON, but didn't want to write the boilerplate from_json
classmethods to convert JSON to Python objects?
Now you don't have to!
fromjson adds a simple decorator for classes, which adds a from_json
classmethod to the class.
It works on all classes, as long as the fields in the class are either Python primitive types (int, float, str, dict, list) or classes with a from_json
classmethod, and the class has type hints for its constuctor.
This means that if you have nested classes which you want to load from JSON, you only need to add a decorator call for each of the classes.
This library is heavily inspired by the excellent Haskell library aeson.
Usage
All the examples have these imports
>>> from dataclasses import dataclass
>>> import json
>>>
>>> from fromjson import fromjson, tojson
Suppose we have the following JSON:
>>> foo = """
... {
... "field": "a string value",
... "another_field": 42
... }
... """
We want to deserialise it into a class defined by:
>>> @dataclass
... class Foo:
... field: str
... another_field: int
Adding a @fromjson
decorator before the class definition adds a from_json
classmethod to the class, which enables us to load it from a dictionary representation:
>>> @dataclass
... @fromjson
... class Foo:
... field: str
... another_field: int
...
>>> Foo.from_json(json.loads(foo))
Foo(field='a string value', another_field=42)
tojson
For completeness, there's also a @tojson
decorator, which does the opposite.
It is used similarly:
>>> @dataclass
... @tojson
... class Foo:
... field: str
... another_field: int
...
>>> json.dumps(Foo("asd", 42).to_json())
'{"field": "asd", "another_field": 42}'
Nested classes
The real power of fromjson is in deserialising user made classes, which have other user made classes as fields. Suppose we have the following nested JSON data:
>>> bird = """
... {
... "name": "Duck",
... "cry": "Quack!",
... "egg": {
... "size": "Medium",
... "color": "White"
... }
... }
... """
We can parse it into the following classes, by adding a @fromjson
call to each class:
>>> @dataclass
... @fromjson
... class Egg:
... size: str
... color: str
...
>>> @dataclass
... @fromjson
... class Bird:
... name: str
... cry: str
... egg: Egg
...
>>> import json
>>> Bird.from_json(json.loads(bird))
Bird(name='Duck', cry='Quack!', egg=Egg(size='Medium', color='White'))
Parsing logic
The json is parsed according to the following logic:
- The argument for
from_json
has to be aMapping
(i.e. an ordinary dictionary is fine) - The type hints for the class are read
- For each type hint, if the type is one of
str
,int
,float
,dict
, orlist
, the corresponding value from the argument mapping is used as-is. - If the type is none of the enumerated primitive types, it has to be a class with a
from_json
classmethod, which is then used to parse the object. - If the type isn't a primitive, and the class doesn't have a
from_json
classmethod, the parsing fails.
If your nested class has some really complicated parsing logic, for which fromjson
is inadequate, you can write a from_json
classmethod by hand.
Then the class can be used inside other classes, which have a @fromjson
decorator call.
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.