Skip to content

Library for parsing nested JSONs into predefined classes 🔨✨

License

Notifications You must be signed in to change notification settings

abionics/jsonizer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jsonizer

It is a library for parsing nested JSONs into predefined classes 🔨✨

In many cases you can use dataclasses or pydantic for parsing JSON into Python classes. But sometimes you need to parse JSON into some predefined classes. You can't change this classes, or it is too time-consuming. For example, this classes can be imported from another library. In this case, this is an ideal solution for you :)

Reasons to use jsonizer

  • Supports nested classes
  • Fastest class detection
  • No dependencies

Installation

pip install jsonizer

Usage sample

from jsonizer import Jsonizer

class Egg:
    def __init__(self, size, color='white'):
        self._size = size
        self._color = color
    def __repr__(self):
        return f'{self._color} egg with size {self._size}'

class Bird:
    def __init__(self, name, eggs):
        self._name = name
        self._eggs = eggs
    def __repr__(self):
        return f'Bird "{self._name}" with eggs {self._eggs}'

json_data = {
    'name': 'Duck',
    'eggs': [{
        'size': 12,
    }, {
        'size': 69,
        'color': 'purple',
    }]
}
parser = Jsonizer(Bird, Egg)
bird = parser.parse(json_data)
print(bird)
# >>> Bird "Duck" with eggs [white egg with size 12, purple egg with size 69]

This sample can be found here. For simplicity, there are no type hints (and no PEP8 style). But jsonizer allows and insists on using type hints. Here is same sample but with type hints

Parsing initial arguments

Class Jsonizer require the list of classes in that JSONs can be parsed as first argument, they can be in any order

Optional arguments
Name Type Default Description
ignore_ambiguity bool False Ignore exceptions when dicts can be matched to two or more constructors (see exceptions block)
disallow_dicts bool False Disallow to have dict as class argument (see exceptions block)
lowercase_keys bool False Lowercase all keys (names) in input JSON
replace_space str None If not None, replace space in keys (names) in input JSON with this value

Parsing functions

Function Description Sample
parse(dict/list) Parse object of list of objects parse({'name': 'Alice'})
parse_string(str) Parse JSON string parse('{"name": "Alice"}')
parse_file(str) Parse JSON file by filename parse('sample.json')

Exceptions

There are 3+1 kind of exceptions:

1. AmbiguityParamsException

It appears when jsonizer two classes can have common init params. In example below, json data {"name": "Alice"} can be matched to both classes. You can ignore such situations by passing ignore_ambiguity=True to parser

class Person:
    def __init__(self, name: str):
        # .. some logic ...
class Worker:
    def __init__(self, name: str, income: int = 0):
        # .. some logic ...

parser = Jsonizer(Worker, Person)
# >>> jsonizer.exceptions.AmbiguityParamsException: Some signatures can be matched to class "<class 'sample.Worker'>" and "<class 'sample.Person'>" simultaneously

parser = Jsonizer(Worker, Person, ignore_ambiguity=True)
parser.parse(...)
2. UnparsedJsonException

In some rarely cases (I really don't know why) you may want to not have dicts as arguments. You can reach this by passing disallow_dicts=True to parser

class Person:
    def __init__(self, name: str, contacts: Any):
        # .. some logic ...

person_data = {'name': 'Alice', 'contacts': {'phone': '123-456-7890'}}

parser = Jsonizer(Person, disallow_dicts=True)
parser.parse(person_data)
# >>> jsonizer.exceptions.UnparsedJsonException: Cannot recognize class for JSON data "{'phone': '123-456-7890'}"

parser = Jsonizer(Person)
person = parser.parse(person_data)
# >> Hi! I am Alice, my contacts are {'phone': '123-456-7890'}
3. FullyUnparsedException

Cannot parse main dict (root/first elements) into one of passed classes. Check keys of JSON data, is they really matched to any class

4. JSONDecodeError (standard Python exception)

Default Python exception in case of invalid JSON file or string. Check your JSON, 99.69% that it is invalid. You can check it here. See more in documentation

PS in JSON you must use double quotes " instead of single ', and null instead of None

FAQ

Q: Why is it so fast?

A: It uses hashes to represent all possible constructor (regardless the arguments order)

Q: What does parser do with self, *args and **kwargs?

A: It skips them, even if they have different name

Q: Where there are so few tests?

A: They are waiting while you will code them :)

More

PyPI: https://pypi.org/project/jsonizer

Repository: https://github.com/abionics/jsonizer

Developer: Alex Ermolaev (Abionics)

Email: abionics.dev@gmail.com

License: MIT (see LICENSE.txt)

About

Library for parsing nested JSONs into predefined classes 🔨✨

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published