Edit on GitHub

jsonapy

JSON:APy - Dumping JSON:API in Python

WIP: this library is still in early development phase.

jsonapy is a Python library for dumping models into JSON:API-compliant JSON.

This library is provided under the MIT License, its source is hosted on GitHub.

Basics

This package lets you define models and dump them into dictionaries with the JSON:API structure. First, define a resource, it is a class inheriting from jsonapy.base.BaseResource in which the fields are defined with annotations:

import jsonapy

class PersonResource(jsonapy.BaseResource):
    id: int
    first_name: str
    last_name: str

    class Meta:
        resource_name = "person"

The Meta inner class is used to set some fields-typing-unrelated configuration, like the the resource name (the "type" field). Instances of this resource can be now dumped into JSON:API-structured dictionaries:

guido = PersonResource(id=1, first_name="Guido", last_name="Van Rossum")
guido.jsonapi_dict(required_attributes="__all__")

# {'type': 'person',
#  'id': 1,
#  'attributes': {'firstName': 'Guido', 'lastName': 'Van Rossum'}}

It is also possible to specify the fields to dump in the dictionary.

guido.jsonapi_dict(required_attributes=["first_name"])

# {'type': 'person',
#  'id': 1,
#  'attributes': {'firstName': 'Guido'}}

Instead of a dictionary, the dump() method allows to get a JSON string:

guido.dump(required_attributes=["first_name"])

# '{"type": "person", "id": 1, "attributes": {"firstName": "Guido"}}'

Resource links can be specified by registering factories functions that will be used to generate them using the register_link_factory() method:

PersonResource.register_link_factory("self", lambda x: f"http://my.api/persons/{x})

Now, the "self" link can be used when exporting the object as a dictionary:

guido.jsonapi_dict(
    links={"self": {"x": guido.id}},
    required_attributes="__all__")

# {
#   'type': 'person',
#   'id': 1,
#   'attributes': {
#     'firstName': 'Guido',
#     'lastName': 'Van Rossum'
#   },
#   'links': {'self': 'http://my.api/persons/1'}
# }

Links can also be added at dumping time without being registered by providing a raw string.

guido.jsonapi_dict(
    links={
        "self": {"x": guido.id},
        "languages": "http://my.api/persons/1/languages"},
    required_attributes="__all__")

# {
#   'type': 'person',
#   'id': 1,
#   'attributes': {
#     'firstName': 'Guido',
#     'lastName': 'Van Rossum'
#   },
#   'links': {
#     'self': 'http://my.api/persons/1'
#     'languages': 'http://my.api/persons/1/languages'
#   }
# }

Relationships

You can create related models:

class ArticleResource(jsonapy.BaseResource):
    id: int
    title: str
    author: PersonResource

    class Meta:
        resource_name = "article"
        # links factories can also be specified in Meta:
        links_factories = {
            "self": lambda x: f"http://my.api/articles/{x}",
            # for relationships, prefix the relationship name
            "author__related": lambda x: f"http://my.api/articles/{x}/author"}

Then, when you export an article, you can indicate the relationships you want to dump by passing a dictionary to the relationships parameter.

zola = PersonResource(id=1, first_name="Emile", last_name="Zola")
jaccuse = ArticleResource(id=1, title="J'accuse… !", author=zola)
jaccuse.jsonapi_dict(
    required_attributes="__all__",
    links={"self": {"x": jaccuse.id}},
    relationships={
        "author": {
            "data": True,
            "links": {"related": {"x": jaccuse.id}}}
)

# {
#   'type': 'article',
#   'id': 1,
#   'attributes': {'title': "J'accuse… !"},
#   'links': {'self': 'http://my.api/articles/1'},
#   'relationships': {
#     'author': {
#       'data': {'type': 'person', 'id': 1},
#       'links': {'related': 'http://my.api/articles/1/author'}
#     }
#   }
# }

Accessing metadata about resources

The jsonapy.functions module provide top level functions for accessing some information about resource classes.

Reference of resource definition

For a more complete reference about resources, see jsonapy.base module.

View Source
# Copyright (c) 2021 Guillaume Fayard
# This library is licensed under the MIT license
# For a complete copy of the license, see the LICENSE file.

""" # JSON:APy - Dumping JSON:API in Python

> **WIP:** this library is still in early development phase.

`jsonapy` is a Python library for dumping models into
[JSON:API-compliant](https://jsonapi.org/) JSON.

This library is provided under the [MIT License](https://pycolore.mit-license.org),
its source is hosted on [GitHub](https://github.com/Arkelis/jsonapy).

## Basics

This package lets you define models and dump them into dictionaries with the
JSON:API structure. First, define a resource, it is a class inheriting from
`jsonapy.base.BaseResource` in which the fields are defined with annotations:

```python
import jsonapy

class PersonResource(jsonapy.BaseResource):
    id: int
    first_name: str
    last_name: str

    class Meta:
        resource_name = "person"
```

The `Meta` inner class is used to set some fields-typing-unrelated configuration,
like the the resource name (the `"type"` field). Instances of this resource
can be now dumped into JSON:API-structured dictionaries:

```python
guido = PersonResource(id=1, first_name="Guido", last_name="Van Rossum")
guido.jsonapi_dict(required_attributes="__all__")

# {'type': 'person',
#  'id': 1,
#  'attributes': {'firstName': 'Guido', 'lastName': 'Van Rossum'}}
```

It is also possible to specify the fields to dump in the dictionary.

```python
guido.jsonapi_dict(required_attributes=["first_name"])

# {'type': 'person',
#  'id': 1,
#  'attributes': {'firstName': 'Guido'}}
```

Instead of a dictionary, the `dump()` method allows to get a JSON string:

```python
guido.dump(required_attributes=["first_name"])

# '{"type": "person", "id": 1, "attributes": {"firstName": "Guido"}}'
```

## Links

Resource links can be specified by registering factories functions that will
be used to generate them using the `register_link_factory()` method:

```python
PersonResource.register_link_factory("self", lambda x: f"http://my.api/persons/{x})
```

Now, the `"self"` link can be used when exporting the object as a dictionary:

```python
guido.jsonapi_dict(
    links={"self": {"x": guido.id}},
    required_attributes="__all__")

# {
#   'type': 'person',
#   'id': 1,
#   'attributes': {
#     'firstName': 'Guido',
#     'lastName': 'Van Rossum'
#   },
#   'links': {'self': 'http://my.api/persons/1'}
# }
```

Links can also be added at dumping time without being registered by providing
a raw string.

```python
guido.jsonapi_dict(
    links={
        "self": {"x": guido.id},
        "languages": "http://my.api/persons/1/languages"},
    required_attributes="__all__")

# {
#   'type': 'person',
#   'id': 1,
#   'attributes': {
#     'firstName': 'Guido',
#     'lastName': 'Van Rossum'
#   },
#   'links': {
#     'self': 'http://my.api/persons/1'
#     'languages': 'http://my.api/persons/1/languages'
#   }
# }
```

## Relationships

You can create related models:

```python
class ArticleResource(jsonapy.BaseResource):
    id: int
    title: str
    author: PersonResource

    class Meta:
        resource_name = "article"
        # links factories can also be specified in Meta:
        links_factories = {
            "self": lambda x: f"http://my.api/articles/{x}",
            # for relationships, prefix the relationship name
            "author__related": lambda x: f"http://my.api/articles/{x}/author"}
```

Then, when you export an article, you can indicate the relationships you want
to dump by passing a dictionary to the `relationships` parameter.

```python
zola = PersonResource(id=1, first_name="Emile", last_name="Zola")
jaccuse = ArticleResource(id=1, title="J'accuse… !", author=zola)
jaccuse.jsonapi_dict(
    required_attributes="__all__",
    links={"self": {"x": jaccuse.id}},
    relationships={
        "author": {
            "data": True,
            "links": {"related": {"x": jaccuse.id}}}
)

# {
#   'type': 'article',
#   'id': 1,
#   'attributes': {'title': "J'accuse… !"},
#   'links': {'self': 'http://my.api/articles/1'},
#   'relationships': {
#     'author': {
#       'data': {'type': 'person', 'id': 1},
#       'links': {'related': 'http://my.api/articles/1/author'}
#     }
#   }
# }

```

## Accessing metadata about resources

The `jsonapy.functions` module provide top level functions for accessing some
information about resource classes.

## Reference of resource definition

For a more complete reference about resources, see `jsonapy.base` module.
"""


__version__ = "0.1.1"

from .base import BaseResource
from .functions import fields_types
from .functions import relationships_names
from .functions import attributes_names