marshmallow-jsonapi

Release v0.24.0. (Changelog)

JSON API 1.0 (https://jsonapi.org) formatting with marshmallow.

marshmallow-jsonapi provides a simple way to produce JSON API-compliant data in any Python web framework.

from marshmallow_jsonapi import Schema, fields


class PostSchema(Schema):
    id = fields.Str(dump_only=True)
    title = fields.Str()

    author = fields.Relationship(
        related_url="/authors/{author_id}",
        related_url_kwargs={"author_id": "<author.id>"},
    )

    comments = fields.Relationship(
        related_url="/posts/{post_id}/comments",
        related_url_kwargs={"post_id": "<id>"},
        # Include resource linkage
        many=True,
        include_resource_linkage=True,
        type_="comments",
    )

    class Meta:
        type_ = "posts"
        strict = True


post_schema = PostSchema()
post_schema.dump(post)
# {
#     "data": {
#         "id": "1",
#         "type": "posts"
#         "attributes": {
#             "title": "JSON API paints my bikeshed!"
#         },
#         "relationships": {
#             "author": {
#                 "links": {
#                     "related": "/authors/9"
#                 }
#             },
#             "comments": {
#                 "data": [
#                     {"id": 5, "type": "comments"},
#                     {"id": 12, "type": "comments"}
#                 ],
#                 "links": {
#                     "related": "/posts/1/comments/"
#                 }
#             }
#         },
#     }
# }

Installation

pip install marshmallow-jsonapi

Guide

Quickstart

Note

The following guide assumes some familiarity with the marshmallow API. To learn more about marshmallow, see its official documentation at https://marshmallow.readthedocs.io.

Declaring schemas

Let’s start with a basic post “model”.

class Post:
    def __init__(self, id, title):
        self.id = id
        self.title = title

Declare your schemas as you would with marshmallow.

A Schema MUST define:

  • An id field

  • The type_ class Meta option

It is RECOMMENDED to set strict mode to True.

Automatic self-linking is supported through these Meta options:

  • self_url specifies the URL to the resource itself

  • self_url_kwargs specifies replacement fields for self_url

  • self_url_many specifies the URL the resource when a collection (many) are serialized

from marshmallow_jsonapi import Schema, fields


class PostSchema(Schema):
    id = fields.Str(dump_only=True)
    title = fields.Str()

    class Meta:
        type_ = "posts"
        self_url = "/posts/{id}"
        self_url_kwargs = {"id": "<id>"}
        self_url_many = "/posts/"

These URLs can be auto-generated by specifying self_view, self_view_kwargs and self_view_many instead when using the Flask integration.

Serialization

Objects will be serialized to JSON API documents with primary data.

post = Post(id="1", title="Django is Omakase")
PostSchema().dump(post)
# {
#     'data': {
#         'id': '1',
#         'type': 'posts',
#         'attributes': {'title': 'Django is Omakase'},
#         'links': {'self': '/posts/1'}
#     },
#     'links': {'self': '/posts/1'}
# }

Relationships

The Relationship field is used to serialize relationship objects. For example, a Post may have an author and comments associated with it.

class User:
    def __init__(self, id, name):
        self.id = id
        self.name = name


class Comment:
    def __init__(self, id, body, author):
        self.id = id
        self.body = body
        self.author = author


class Post:
    def __init__(self, id, title, author, comments=None):
        self.id = id
        self.title = title
        self.author = author  # User object
        self.comments = [] if comments is None else comments  # Comment objects

To serialize links, pass a URL format string and a dictionary of keyword arguments. String arguments enclosed in < > will be interpreted as attributes to pull from the object being serialized. The relationship links can automatically be generated from Flask view names when using the Flask integration.

class PostSchema(Schema):
    id = fields.Str(dump_only=True)
    title = fields.Str()

    author = fields.Relationship(
        self_url="/posts/{post_id}/relationships/author",
        self_url_kwargs={"post_id": "<id>"},
        related_url="/authors/{author_id}",
        related_url_kwargs={"author_id": "<author.id>"},
    )

    class Meta:
        type_ = "posts"


user = User(id="94", name="Laura")
post = Post(id="1", title="Django is Omakase", author=user)
PostSchema().dump(post)
# {
#     'data': {
#         'id': '1',
#         'type': 'posts',
#         'attributes': {'title': 'Django is Omakase'},
#         'relationships': {
#             'author': {
#                 'links': {
#                     'self': '/posts/1/relationships/author',
#                     'related': '/authors/94'
#                 }
#             }
#         }
#     }
# }
Resource linkages

You can serialize resource linkages by passing include_resource_linkage=True and the resource type_ argument.

class PostSchema(Schema):
    id = fields.Str(dump_only=True)
    title = fields.Str()

    author = fields.Relationship(
        self_url="/posts/{post_id}/relationships/author",
        self_url_kwargs={"post_id": "<id>"},
        related_url="/authors/{author_id}",
        related_url_kwargs={"author_id": "<author.id>"},
        # Include resource linkage
        include_resource_linkage=True,
        type_="users",
    )

    class Meta:
        type_ = "posts"


PostSchema().dump(post)
# {
#     'data': {
#         'id': '1',
#         'type': 'posts',
#         'attributes': {'title': 'Django is Omakase'},
#         'relationships': {
#             'author': {
#                 'data': {'type': 'users', 'id': '94'},
#                 'links': {
#                     'self': '/posts/1/relationships/author',
#                     'related': '/authors/94'
#                 }
#             }
#         }
#     }
# }
Compound documents

Compound documents allow to include related resources into the request with the primary resource. In order to include objects, you have to define a Schema for the respective relationship, which will be used to render those objects.

class PostSchema(Schema):
    id = fields.Str(dump_only=True)
    title = fields.Str()

    comments = fields.Relationship(
        related_url="/posts/{post_id}/comments",
        related_url_kwargs={"post_id": "<id>"},
        many=True,
        include_resource_linkage=True,
        type_="comments",
        # define a schema for rendering included data
        schema="CommentSchema",
    )

    author = fields.Relationship(
        self_url="/posts/{post_id}/relationships/author",
        self_url_kwargs={"post_id": "<id>"},
        related_url="/authors/{author_id}",
        related_url_kwargs={"author_id": "<author.id>"},
        include_resource_linkage=True,
        type_="users",
    )

    class Meta:
        type_ = "posts"


class CommentSchema(Schema):
    id = fields.Str(dump_only=True)
    body = fields.Str()

    author = fields.Relationship(
        self_url="/comments/{comment_id}/relationships/author",
        self_url_kwargs={"comment_id": "<id>"},
        related_url="/comments/{author_id}",
        related_url_kwargs={"author_id": "<author.id>"},
        type_="users",
        # define a schema for rendering included data
        schema="UserSchema",
    )

    class Meta:
        type_ = "comments"


class UserSchema(Schema):
    id = fields.Str(dump_only=True)
    name = fields.Str()

    class Meta:
        type_ = "users"

Just as with nested fields the schema can be a class or a string with a simple or fully qualified class name. Make sure to import the schema beforehand.

Now you can include some data in a dump by specifying the include_data argument (also supports nested relations via the dot syntax).

armin = User(id="101", name="Armin")
laura = User(id="94", name="Laura")
steven = User(id="23", name="Steven")
comments = [
    Comment(id="5", body="Marshmallow is sweet like sugar!", author=steven),
    Comment(id="12", body="Flask is Fun!", author=armin),
]
post = Post(id="1", title="Django is Omakase", author=laura, comments=comments)

PostSchema(include_data=("comments", "comments.author")).dump(post)
# {
#     'data': {
#         'id': '1',
#         'type': 'posts',
#         'attributes': {'title': 'Django is Omakase'},
#         'relationships': {
#             'author': {
#                 'data': {'type': 'users', 'id': '94'},
#                 'links': {
#                     'self': '/posts/1/relationships/author',
#                     'related': '/authors/94'
#                 }
#             },
#             'comments': {
#                 'data': [
#                     {'type': 'comments', 'id': '5'},
#                     {'type': 'comments', 'id': '12'}
#                 ],
#                 'links': {
#                     'related': '/posts/1/comments'
#                 }
#             }
#         }
#     },
#     'included': [
#         {
#             'id': '5',
#             'type': 'comments',
#             'attributes': {'body': 'Marshmallow is sweet like sugar!'},
#             'relationships': {
#                 'author': {
#                     'data': {'type': 'users', 'id': '23'},
#                     'links': {
#                         'self': '/comments/5/relationships/author',
#                         'related': '/comments/23'
#                     }
#                 }
#             }
#         },
#         {
#             'id': '12',
#             'type': 'comments',
#             'attributes': {'body': 'Flask is Fun!'},
#             'relationships': {
#                 'author': {
#                     'data': {'type': 'users', 'id': '101'},
#                     'links': {
#                         'self': '/comments/12/relationships/author',
#                         'related': '/comments/101'
#                     }
#                 }
#             },
#
#         },
#         {
#             'id': '23',
#             'type': 'users',
#             'attributes': {'name': 'Steven'}
#         },
#         {
#             'id': '101',
#             'type': 'users',
#             'attributes': {'name': 'Armin'}
#         }
#     ]
# }

Meta Information

The DocumentMeta field is used to serialize the meta object within a document’s “top level”.

from marshmallow_jsonapi import Schema, fields


class UserSchema(Schema):
    id = fields.Str(dump_only=True)
    name = fields.Str()
    document_meta = fields.DocumentMeta()

    class Meta:
        type_ = "users"


user = {"name": "Alice", "document_meta": {"page": {"offset": 10}}}
UserSchema().dump(user)
# {
#     "meta": {
#         "page": {
#             "offset": 10
#         }
#     },
#     "data": {
#         "id": "1",
#         "type": "users"
#         "attributes": {"name": "Alice"},
#     }
# }

The ResourceMeta field is used to serialize the meta object within a resource object.

from marshmallow_jsonapi import Schema, fields


class UserSchema(Schema):
    id = fields.Str(dump_only=True)
    name = fields.Str()
    resource_meta = fields.ResourceMeta()

    class Meta:
        type_ = "users"


user = {"name": "Alice", "resource_meta": {"active": True}}
UserSchema().dump(user)
# {
#     "data": {
#         "type": "users",
#         "attributes": {"name": "Alice"},
#         "meta": {
#             "active": true
#         }
#     }
# }

Errors

Schema.load() and Schema.validate() will return JSON API-formatted Error objects.

from marshmallow_jsonapi import Schema, fields
from marshmallow import validate, ValidationError


class AuthorSchema(Schema):
    id = fields.Str(dump_only=True)
    first_name = fields.Str(required=True)
    last_name = fields.Str(required=True)
    password = fields.Str(load_only=True, validate=validate.Length(6))
    twitter = fields.Str()

    class Meta:
        type_ = "authors"


author_data = {
    "data": {"type": "users", "attributes": {"first_name": "Dan", "password": "short"}}
}
AuthorSchema().validate(author_data)
# {
#     'errors': [
#         {
#             'detail': 'Missing data for required field.',
#             'source': {
#                 'pointer': '/data/attributes/last_name'
#             }
#         },
#         {
#             'detail': 'Shorter than minimum length 6.',
#             'source': {
#                 'pointer': '/data/attributes/password'
#             }
#         }
#     ]
# }

If an invalid “type” is passed in the input data, an IncorrectTypeError is raised.

from marshmallow_jsonapi.exceptions import IncorrectTypeError

author_data = {
    "data": {
        "type": "invalid-type",
        "attributes": {
            "first_name": "Dan",
            "last_name": "Gebhardt",
            "password": "verysecure",
        },
    }
}

try:
    AuthorSchema().validate(author_data)
except IncorrectTypeError as err:
    pprint(err.messages)
# {
#     'errors': [
#         {
#             'detail': 'Invalid type. Expected "users".',
#             'source': {
#                 'pointer': '/data/type'
#             }
#         }
#     ]
# }

Inflection

You can optionally specify a function to transform attribute names. For example, you may decide to follow JSON API’s recommendation to use “dasherized” names.

from marshmallow_jsonapi import Schema, fields


def dasherize(text):
    return text.replace("_", "-")


class UserSchema(Schema):
    id = fields.Str(dump_only=True)
    first_name = fields.Str(required=True)
    last_name = fields.Str(required=True)

    class Meta:
        type_ = "users"
        inflect = dasherize


UserSchema().dump(user)
# {
#     'data': {
#         'id': '9',
#         'type': 'users',
#         'attributes': {
#             'first-name': 'Dan',
#             'last-name': 'Gebhardt'
#         }
#     }
# }

Flask integration

marshmallow-jsonapi includes optional utilities to integrate with Flask.

A Flask-specific schema in marshmallow_jsonapi.flask can be used to auto-generate self-links based on view names instead of hard-coding URLs.

Additionally, the Relationship field in the marshmallow_jsonapi.flask module allows you to pass view names instead of path templates to generate relationship links.

from marshmallow_jsonapi import fields
from marshmallow_jsonapi.flask import Relationship, Schema


class PostSchema(Schema):
    id = fields.Str(dump_only=True)
    title = fields.Str()

    author = fields.Relationship(
        self_view="post_author",
        self_url_kwargs={"post_id": "<id>"},
        related_view="author_detail",
        related_view_kwargs={"author_id": "<author.id>"},
    )

    comments = Relationship(
        related_view="post_comments",
        related_view_kwargs={"post_id": "<id>"},
        many=True,
        include_resource_linkage=True,
        type_="comments",
    )

    class Meta:
        type_ = "posts"
        self_view = "post_detail"
        self_view_kwargs = {"post_detail": "<id>"}
        self_view_many = "posts_list"

See here for a full example.

API Reference

API Reference

Core

class marshmallow_jsonapi.Schema(*args, **kwargs)[source]

Schema class that formats data according to JSON API 1.0. Must define the type_ class Meta option.

Example:

from marshmallow_jsonapi import Schema, fields

def dasherize(text):
    return text.replace('_', '-')

class PostSchema(Schema):
    id = fields.Str(dump_only=True)  # Required
    title = fields.Str()

    author = fields.HyperlinkRelated(
        '/authors/{author_id}',
        url_kwargs={'author_id': '<author.id>'},
    )

    comments = fields.HyperlinkRelated(
        '/posts/{post_id}/comments',
        url_kwargs={'post_id': '<id>'},
        # Include resource linkage
        many=True, include_resource_linkage=True,
        type_='comments'
    )

    class Meta:
        type_ = 'posts'  # Required
        inflect = dasherize
class Meta[source]

Options object for Schema. Takes the same options as marshmallow.Schema.Meta with the addition of:

  • type_ - required, the JSON API resource type as a string.

  • inflect - optional, an inflection function to modify attribute names.

  • self_url - optional, URL to use to self in links

  • self_url_kwargs - optional, replacement fields for self_url. String arguments enclosed in < > will be interpreted as attributes to pull from the schema data.

  • self_url_many - optional, URL to use to self in top-level links when a collection of resources is returned.

OPTIONS_CLASS

alias of marshmallow_jsonapi.schema.SchemaOpts

check_relations(relations)[source]

Recursive function which checks if a relation is valid.

format_error(field_name, message, index=None)[source]

Override-able hook to format a single error message as an Error object.

See: http://jsonapi.org/format/#error-objects

format_errors(errors, many)[source]

Format validation errors as JSON Error objects.

format_item(item)[source]

Format a single datum as a Resource object.

See: http://jsonapi.org/format/#document-resource-objects

format_items(data, many)[source]

Format data as a Resource object or list of Resource objects.

See: http://jsonapi.org/format/#document-resource-objects

format_json_api_response(data, many, **kwargs)[source]

Post-dump hook that formats serialized data as a top-level JSON API object.

See: http://jsonapi.org/format/#document-top-level

generate_url(link, **kwargs)[source]

Generate URL with any kwargs interpolated.

Hook for adding links to a resource object.

Hook for adding links to the root of the response data.

inflect(text)[source]

Inflect text if the inflect class Meta option is defined, otherwise do nothing.

on_bind_field(field_name, field_obj)[source]

Schema hook override. When binding fields, set data_key to the inflected form of field_name.

wrap_response(data, many)[source]

Wrap data and links according to the JSON API

class marshmallow_jsonapi.SchemaOpts(meta, *args, **kwargs)[source]

Fields

Includes all the fields classes from marshmallow.fields as well as fields for serializing JSON API-formatted hyperlinks.

class marshmallow_jsonapi.fields.BaseRelationship(*, load_default: Any = <marshmallow.missing>, missing: Any = <marshmallow.missing>, dump_default: Any = <marshmallow.missing>, default: Any = <marshmallow.missing>, data_key: Optional[str] = None, attribute: Optional[str] = None, validate: Optional[Union[Callable[[Any], Any], Iterable[Callable[[Any], Any]]]] = None, required: bool = False, allow_none: Optional[bool] = None, load_only: bool = False, dump_only: bool = False, error_messages: Optional[Dict[str, str]] = None, metadata: Optional[Mapping[str, Any]] = None, **additional_metadata)[source]

Base relationship field.

This is used by marshmallow_jsonapi.Schema to determine which fields should be formatted as relationship objects.

See: http://jsonapi.org/format/#document-resource-object-relationships

class marshmallow_jsonapi.fields.DocumentMeta(**kwargs)[source]

Field which serializes to a “meta object” within a document’s “top level”.

Examples:

from marshmallow_jsonapi import Schema, fields

class UserSchema(Schema):
    id = fields.String()
    metadata = fields.DocumentMeta()

    class Meta:
        type_ = 'product'

See: http://jsonapi.org/format/#document-meta

class marshmallow_jsonapi.fields.Relationship(related_url='', related_url_kwargs=None, *, self_url='', self_url_kwargs=None, include_resource_linkage=False, schema=None, many=False, type_=None, id_field=None, **kwargs)[source]

Framework-independent field which serializes to a “relationship object”.

See: http://jsonapi.org/format/#document-resource-object-relationships

Examples:

author = Relationship(
    related_url='/authors/{author_id}',
    related_url_kwargs={'author_id': '<author.id>'},
)

comments = Relationship(
    related_url='/posts/{post_id}/comments/',
    related_url_kwargs={'post_id': '<id>'},
    many=True, include_resource_linkage=True,
    type_='comments'
)

This field is read-only by default.

Parameters
  • related_url (str) – Format string for related resource links.

  • related_url_kwargs (dict) – Replacement fields for related_url. String arguments enclosed in < > will be interpreted as attributes to pull from the target object.

  • self_url (str) – Format string for self relationship links.

  • self_url_kwargs (dict) – Replacement fields for self_url. String arguments enclosed in < > will be interpreted as attributes to pull from the target object.

  • include_resource_linkage (bool) – Whether to include a resource linkage (http://jsonapi.org/format/#document-resource-object-linkage) in the serialized result.

  • schema (marshmallow_jsonapi.Schema) – The schema to render the included data with.

  • many (bool) – Whether the relationship represents a many-to-one or many-to-many relationship. Only affects serialization of the resource linkage.

  • type (str) – The type of resource.

  • id_field (str) – Attribute name to pull ids from if a resource linkage is included.

deserialize(value, attr=None, data=None, **kwargs)[source]

Deserialize value.

Raises

ValidationError – If the value is not type dict, if the value does not contain a data key, and if the value is required but unspecified.

extract_value(data)[source]

Extract the id key and validate the request structure.

serialize(attr, obj, accessor=None)[source]

Pulls the value for the given key from the object, applies the field’s formatting and returns the result.

Parameters
  • attr – The attribute/key to get from the object.

  • obj – The object to access the attribute/key from.

  • accessor – Function used to access values from obj.

  • kwargs – Field-specific keyword arguments.

class marshmallow_jsonapi.fields.ResourceMeta(**kwargs)[source]

Field which serializes to a “meta object” within a “resource object”.

Examples:

from marshmallow_jsonapi import Schema, fields

class UserSchema(Schema):
    id = fields.String()
    meta_resource = fields.ResourceMeta()

    class Meta:
        type_ = 'product'

See: http://jsonapi.org/format/#document-resource-objects

Flask

Flask integration that avoids the need to hard-code URLs for links.

This includes a Flask-specific schema with custom Meta options and a relationship field for linking to related resources.

class marshmallow_jsonapi.flask.Relationship(related_view=None, related_view_kwargs=None, *, self_view=None, self_view_kwargs=None, **kwargs)[source]

Field which serializes to a “relationship object” with a “related resource link”.

See: http://jsonapi.org/format/#document-resource-object-relationships

Examples:

author = Relationship(
    related_view='author_detail',
    related_view_kwargs={'author_id': '<author.id>'},
)

comments = Relationship(
    related_view='posts_comments',
    related_view_kwargs={'post_id': '<id>'},
    many=True, include_resource_linkage=True,
    type_='comments'
)

This field is read-only by default.

Parameters
  • related_view (str) – View name for related resource link.

  • related_view_kwargs (dict) – Path kwargs fields for related_view. String arguments enclosed in < > will be interpreted as attributes to pull from the target object.

  • self_view (str) – View name for self relationship link.

  • self_view_kwargs (dict) – Path kwargs for self_view. String arguments enclosed in < > will be interpreted as attributes to pull from the target object.

  • **kwargs – Same keyword arguments as marshmallow_jsonapi.fields.Relationship.

class marshmallow_jsonapi.flask.Schema(*args, **kwargs)[source]

A Flask specific schema that resolves self URLs from view names.

class Meta[source]

Options object that takes the same options as marshmallow-jsonapi.Schema, but instead of self_url, self_url_kwargs and self_url_many has the following options to resolve the URLs from Flask views:

  • self_view - View name to resolve the self URL link from.

  • self_view_kwargs - Replacement fields for self_view. String attributes enclosed in < > will be interpreted as attributes to pull from the schema data.

  • self_view_many - View name to resolve the self URL link when a collection of resources is returned.

self_url = None
self_url_kwargs = None
self_url_many = None
OPTIONS_CLASS

alias of marshmallow_jsonapi.flask.SchemaOpts

generate_url(view_name, **kwargs)[source]

Generate URL with any kwargs interpolated.

class marshmallow_jsonapi.flask.SchemaOpts(meta, *args, **kwargs)[source]

Options to use Flask view names instead of hard coding URLs.

Exceptions

Exception classes.

exception marshmallow_jsonapi.exceptions.IncorrectTypeError(message=None, actual=None, expected=None)[source]

Raised when client provides an invalid type in a request.

property messages

JSON API-formatted error representation.

exception marshmallow_jsonapi.exceptions.JSONAPIError[source]

Base class for all exceptions in this package.

Utilities

Utility functions.

This module should be considered private API.

marshmallow_jsonapi.utils.resolve_params(obj, params, default=<marshmallow.missing>)[source]

Given a dictionary of keyword arguments, return the same dictionary except with values enclosed in < > resolved to attributes on obj.

marshmallow_jsonapi.utils.tpl(val)[source]

Return value within < > if possible, else return None.

Project info

Changelog

0.24.0 (2020-12-27)

Deprecations/Removals:

  • Drop support for marshmallow 2, which is now EOL (#332).

Bug fixes:

Other changes:

  • Test against Python 3.8 and 3.9 (#332).

0.23.2 (2020-07-20)

Bug fixes:

0.23.1 (2020-03-22)

Bug fixes:

0.23.0 (2020-02-02)

  • Improve performance of link generation from Relationship (#277). Thanks @iamareebjamal for reporting and fixing.

0.22.0 (2019-09-15)

Deprecation/Removals:

  • Drop support for Python 2.7 and 3.5. Only Python>=3.6 is supported (#251).

  • Drop support for marshmallow 3 pre-releases. Only stable versions >=2.15.2 are supported.

  • Remove fields.Meta.

Bug fixes:

  • Address DeprecationWarning raised by Field.fail on marshmallow 3.

0.21.2 (2019-07-01)

Bug fixes:

  • marshmallow 3.0.0rc7 compatibility (#233).

Other changes:

  • Format with pyupgrade and black (#235).

  • Switch to Azure Pipelines for CI (#234).

0.21.1 (2019-05-05)

Bug fixes:

  • marshmallow 3.0.0rc6 cmpatibility (#221).

0.21.0 (2018-12-16)

Bug fixes:

  • Backwards-incompatible: Revert URL quoting introduced in 0.20.2 (#184). If you need quoting, override Schema.generate_url.

from marshmallow_jsonapi import Schema
from werkzeug.urls import url_fix


class MySchema(Schema):
    def generate_url(self, link, **kwargs):
        url = super().generate_url(link, **kwargs)
        return url_fix(url)

Thanks @kgutwin for reporting the issue.

  • Fix Relationship deserialization behavior when required=False (#177). Thanks @aberres for reporting and @scottwernervt for the fix.

Other changes:

  • Test against Python 3.7.

0.20.5 (2018-10-27)

Bug fixes:

  • Fix deserializing id field to non-string types (#179). Thanks @aberres for the catch and patch.

0.20.4 (2018-10-04)

Bug fixes:

  • Fix bug where multi-level nested relationships would not be properly deserialized (#127). Thanks @ww3pl for the catch and patch.

0.20.3 (2018-09-13)

Bug fixes:

  • Fix missing load validation when data is not a collection but many=True (#161). Thanks @grantHarris.

0.20.2 (2018-08-15)

Bug fixes:

Other changes:

  • Fix tests against marshmallow 3.0.0b13.

0.20.1 (2018-07-15)

Bug fixes:

  • Fix deserializing missing with a Relationship field (#130). Thanks @kumy for the catch and patch.

0.20.0 (2018-06-10)

Bug fixes:

  • Fix serialization of id for Relationship fields when attribute is set (#69). Thanks @jordal for reporting and thanks @scottwernervt for the fix.

Note: The above fix could break some code that set Relationship.id_field before instantiating it. Set Relationship.default_id_field instead.

# before
fields.Relationship.id_field = "item_id"

# after
fields.Relationship.default_id_field = "item_id"

Support:

0.19.0 (2018-05-27)

Features:

  • Schemas passed to fields.Relationship will inherit context from the parent schema (#84). Thanks @asteinlein and @scottwernervt for the PRs.

0.18.0 (2018-05-19)

Features:

  • Add fields.ResourceMeta for serializing a resource-level meta object (#107). Thanks @scottwernervt.

Other changes:

  • Backwards-incompatible: Drop official support for Python 3.4.

0.17.0 (2018-04-29)

Features:

0.16.0 (2017-11-08)

Features:

  • Add support for exluding or including nested fields on relationships (#94). Thanks @scottwernervt for the PR.

Other changes:

  • Backwards-incompatible: Drop support for marshmallow<2.8.0

0.15.1 (2017-08-23)

Bug fixes:

  • Fix pointer for id in error objects (#90). Thanks @rgant for the catch and patch.

0.15.0 (2017-06-27)

Features:

0.14.0 (2017-04-30)

Features:

  • Relationship respects its passed Schema's get_attribute method when getting the id field for resource linkages (#80). Thanks @scmmmh for the PR.

0.13.0 (2017-04-18)

Features:

  • Add support for including deeply nested relationships in compount documents (#61). Thanks @mrhanky17 for the PR.

0.12.0 (2017-04-16)

Features:

  • Use default attribute value instead of raising exception if relationship is None on Relationship field (#75). Thanks @akira-dev.

0.11.1 (2017-04-06)

Bug fixes:

  • Fix formatting JSON pointer when serializing an invalid object at index 0 (#77). Thanks @danpoland for the catch and patch.

0.11.0 (2017-03-12)

Bug fixes:

  • Fix compatibility with marshmallow 3.x.

Other changes:

  • Backwards-incompatible: Remove unused utils.get_value_or_raise function.

0.10.2 (2017-03-08)

Bug fixes:

  • Fix format of error object returned when data key is not included in input (#66). Thanks @RazerM.

  • Fix serializing compound documents when Relationship is passed a schema class and many=True (#67). Thanks @danpoland for the catch and patch.

0.10.1 (2017-02-05)

Bug fixes:

  • Serialize None and empty lists ([]) to valid JSON-API objects (#58). Thanks @rgant for reporting and sending a PR.

0.10.0 (2017-01-05)

Features:

  • Add fields.Meta for (de)serializing meta data on resource objects (#28). Thanks @rubdos for the suggestion and initial work. Thanks @RazerM for the PR.

Other changes:

  • Test against Python 3.6.

0.9.0 (2016-10-08)

Features:

  • Add Flask-specific schema with class Meta options for self link generation: self_view, self_view_kwargs, and self_view_many (#51). Thanks @asteinlein.

Bug fixes:

  • Fix formatting of validation error messages on newer versions of marshmallow.

Other changes:

  • Drop official support for Python 3.3.

0.8.0 (2016-06-20)

Features:

  • Add support for compound documents (#11). Thanks @Tim-Erwin and @woodb for implementing this.

  • Backwards-incompatible: Remove include_data parameter from Relationship. Use include_resource_linkage instead.

0.7.1 (2016-05-08)

Bug fixes:

  • Format correction for error objects (#47). Thanks @ZeeD26 for the PR.

0.7.0 (2016-04-03)

Features:

  • Correctly format messages attribute of ValidationError raised when type key is missing in input (#43). Thanks @ZeeD26 for the catch and patch.

  • JSON pointers for error objects for relationships will point to the data key (#41). Thanks @cmanallen for the PR.

0.6.0 (2016-03-24)

Features:

  • Relationship deserialization improvements: properly validate to-one and to-many relatinoships and validate the presense of the data key (#37). Thanks @cmanallen for the PR.

  • attributes is no longer a required key in the data object (#39, #42). Thanks @ZeeD26 for reporting and @cmanallen for the PR.

  • Added id serialization (#39). Thanks again @cmanallen.

0.5.0 (2016-02-08)

Features:

  • Add relationship deserialization (#15).

  • Allow serialization of foreign key attributes (#32).

  • Relationship IDs serialize to strings, as is required by JSON-API (#31).

  • Relationship field respects dump_to parameter (#33).

Thanks @cmanallen for all of these changes.

Other changes:

  • The minimum supported marshmallow version is 2.3.0.

0.4.2 (2015-12-21)

Bug fixes:

  • Relationship names are inflected when appropriate (#22). Thanks @angelosarto for reporting.

0.4.1 (2015-12-19)

Bug fixes:

  • Fix serializing null and empty relationships with flask.Relationship (#24). Thanks @floqqi for the catch and patch.

0.4.0 (2015-12-06)

  • Correctly serialize null and empty relationships (#10). Thanks @jo-tham for the PR.

  • Add self_url, self_url_kwargs, and self_url_many class Meta options for adding self links. Thanks @asteinlein for the PR.

0.3.0 (2015-10-18)

  • Backwards-incompatible: Replace HyperlinkRelated with Relationship field. Supports related links (related), relationship links (self), and resource linkages.

  • Backwards-incompatible: Validate and deserialize JSON API-formatted request payloads.

  • Fix error formatting when many=True.

  • Fix error formatting in strict mode.

0.2.2 (2015-09-26)

  • Fix for marshmallow 2.0.0 compat.

0.2.1 (2015-09-16)

  • Compatibility with marshmallow>=2.0.0rc2.

0.2.0 (2015-09-13)

Features:

  • Add framework-independent HyperlinkRelated field.

  • Support inflection of attribute names via the inflect class Meta option.

Bug fixes:

  • Fix for making HyperlinkRelated read-only by defualt.

Support:

  • Docs updates.

  • Tested on Python 3.5.

0.1.0 (2015-09-12)

  • First PyPI release.

  • Include Schema that serializes objects to resource objects.

  • Flask-compatible HyperlinkRelate field for serializing relationships.

  • Errors are formatted as JSON API errror objects.

Authors

Lead

Contributors (chronological)

Contributing Guidelines

Questions, Feature Requests, Bug Reports, and Feedback…

…should all be reported on the Github Issue Tracker .

Setting Up for Local Development

  1. Fork marshmallow-jsonapi on Github.

$ git clone https://github.com/marshmallow-code/marshmallow-jsonapi.git
$ cd marshmallow-jsonapi
  1. Install development requirements. It is highly recommended that you use a virtualenv. Use the following command to install an editable version of marshmallow-jsonapi along with its development requirements.

# After activating your virtualenv
$ pip install -e '.[dev]'
  1. Install the pre-commit hooks, which will format and lint your git staged files.

# The pre-commit CLI was installed above
$ pre-commit install

Git Branch Structure

Marshmallow abides by the following branching model:

dev

Current development branch. New features should branch off here.

X.Y-line

Maintenance branch for release X.Y. Bug fixes should be sent to the most recent release branch. The maintainer will forward-port the fix to dev. Note: exceptions may be made for bug fixes that introduce large code changes.

Always make a new branch for your work, no matter how small. Also, do not put unrelated changes in the same branch or pull request. This makes it more difficult to merge your changes.

Pull Requests

1. Create a new local branch.

$ git checkout -b name-of-feature dev

2. Commit your changes. Write good commit messages.

$ git commit -m "Detailed commit message"
$ git push origin name-of-feature
  1. Before submitting a pull request, check the following:

  • If the pull request adds functionality, it is tested and the docs are updated.

  • You’ve added yourself to AUTHORS.rst.

  1. Submit a pull request to marshmallow-code:dev or the appropriate maintenance branch. The CI build must be passing before your pull request is merged.

Running tests

To run all To run all tests:

$ pytest

To run syntax checks:

$ tox -e lint

(Optional) To run tests in all supported Python versions in their own virtual environments (must have each interpreter installed):

$ tox

Documentation

Contributions to the documentation are welcome. Documentation is written in reStructuredText (rST). A quick rST reference can be found here. Builds are powered by Sphinx.

To build the docs in “watch” mode:

$ tox -e watch-docs

Changes in the docs/ directory will automatically trigger a rebuild.

License

Copyright 2015-2020 Steven Loria and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.