Skip to main content

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 a Mapping (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, or list, 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fromjson-0.1.0.tar.gz (3.7 kB view hashes)

Uploaded Source

Built Distribution

fromjson-0.1.0-py3-none-any.whl (3.5 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page