Skip to main content

marshmallow-jsonschema: JSON Schema formatting with marshmallow

Build Status Code style: black

marshmallow-jsonschema translates marshmallow schemas into JSON Schema Draft v7 compliant documents.

Why would I want my schema translated to JSON?

A few common reasons:

  • Render a marshmallow schema as a form in another runtime (web browser, mobile, native desktop) where you can't import Python.
  • Validate request/response bodies in an API gateway or contract-test layer that consumes JSON Schema directly.
  • Publish your schema as documentation alongside an OpenAPI spec.

Installation

Requires Python 3.9+ and marshmallow 3.13 or later (works on both marshmallow 3 and marshmallow 4).

pip install marshmallow-jsonschema

For older environments:

  • marshmallow 2 → marshmallow-jsonschema<0.11
  • Python 3.6–3.8 or marshmallow 3.11–3.12 → marshmallow-jsonschema<0.14
  • A marshmallow-4-broken intermediate state → marshmallow-jsonschema<0.14 (with marshmallow<4)

Client tools that render forms from JSON Schema

Examples

Simple example

from marshmallow import Schema, fields
from marshmallow_jsonschema import JSONSchema

class UserSchema(Schema):
    username = fields.String()
    age = fields.Integer()
    birthday = fields.Date()

JSONSchema().dump(UserSchema())

Yields:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$ref": "#/definitions/UserSchema",
    "definitions": {
        "UserSchema": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "age": {"title": "age", "type": "integer"},
                "birthday": {"title": "birthday", "type": "string", "format": "date"},
                "username": {"title": "username", "type": "string"}
            }
        }
    }
}

Nested example

Nested schemas land in definitions and are referenced via $ref:

from marshmallow import Schema, fields
from marshmallow_jsonschema import JSONSchema

class AddressSchema(Schema):
    street = fields.String()
    city = fields.String()

class UserSchema(Schema):
    name = fields.String()
    address = fields.Nested(AddressSchema)

JSONSchema().dump(UserSchema())

Yields:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$ref": "#/definitions/UserSchema",
    "definitions": {
        "AddressSchema": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "city": {"title": "city", "type": "string"},
                "street": {"title": "street", "type": "string"}
            }
        },
        "UserSchema": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "address": {"type": "object", "$ref": "#/definitions/AddressSchema"},
                "name": {"title": "name", "type": "string"}
            }
        }
    }
}

fields.Nested("Self") and fields.Nested(lambda: SomeSchema()) are both supported for recursive references.

Top-level array (many=True)

Passing many=True to a schema describes a list of objects rather than a single one; the dumped JSON Schema reflects that with an array envelope:

JSONSchema().dump(UserSchema(many=True))

Yields:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {"UserSchema": { ... }},
    "type": "array",
    "items": {"$ref": "#/definitions/UserSchema"}
}

Flask + JSON Schema form rendering

A complete runnable Flask example lives at example/example.py. It exposes a marshmallow schema as JSON Schema and renders it as a form using json-editor — pure JS, no build pipeline, drop in via CDN:

pip install -r example/requirements.txt
python example/example.py
# open http://127.0.0.1:5000/

For a richer React-based alternative, see ReactJsonSchemaFormJSONSchema below.

Validators

Marshmallow's standard validators translate automatically into JSON Schema constraints when the field is dumped:

Validator JSON Schema output
validate.Length(min=, max=) minLength / maxLength for strings, minItems / maxItems for lists & nested
validate.Range(min=, max=, min_inclusive=, max_inclusive=) minimum / maximum (or exclusiveMinimum / exclusiveMaximum)
validate.OneOf(choices, labels=) enum (and the non-standard enumNames for compatibility with react-jsonschema-form)
validate.Equal(value) enum: [value]
validate.Regexp(pattern) pattern
validate.ContainsOnly(choices, labels=) items.anyOf: [{const}, ...] + uniqueItems: true
from marshmallow import Schema, fields, validate
from marshmallow_jsonschema import JSONSchema

class UserSchema(Schema):
    age = fields.Integer(validate=validate.Range(min=0, max=150))
    name = fields.String(validate=validate.Length(min=1, max=100))
    role = fields.String(validate=validate.OneOf(["admin", "user"]))

For a custom validator that's a subclass of one of the above, set _jsonschema_base_validator_class = validate.<Base> on it so the translation still fires.

Enums

marshmallow.fields.Enum (added in marshmallow 3.18) is supported out of the box and emits the enum-member names. The third-party marshmallow-enum EnumField is also supported when installed; native Enum is preferred when both are present.

by_value=True enums are supported when every member's value is a string — the common pattern for serialising enums as their string value in the wire format:

class Status(str, Enum):
    ACTIVE = "active"
    INACTIVE = "inactive"

class S(Schema):
    status = fields.Enum(Status, by_value=True)
# {"status": {"enum": ["active", "inactive"], "type": "string"}}

Mixed-type or non-string enum values still raise NotImplementedError — use the class MyEnum(str, Enum) pattern, or load by name instead.

Advanced usage

Schema-level title and description

Setting title or description on a schema's inner Meta class emits them at the corresponding definition entry:

class UserSchema(Schema):
    class Meta:
        title = "User"
        description = "A user account record."

    name = fields.String()

Customizing the definitions path

By default nested schemas live under #/definitions/<Name>. Pass definitions_path to use a different single-segment key:

JSONSchema(definitions_path="schemas").dump(MySchema())
# {"$ref": "#/schemas/MySchema", "schemas": {...}, ...}

Multi-segment paths (e.g. "components/schemas") are rejected because they would produce a flat dict key with a slash in it rather than the nested structure consumers expect — wrap the output yourself if you need that shape.

Custom field types

Add a _jsonschema_type_mapping method to your field so we know how to serialize it. Field-level metadata={...} and dump_default values are then merged in automatically, so a single mapping method gets you the full set of standard schema attributes.

class Colour(fields.Field):
    def _jsonschema_type_mapping(self):
        return {"type": "string"}

    def _serialize(self, value, attr, obj):
        r, g, b = value
        return "#%02X%02X%02X" % (r, g, b)


class UserSchema(Schema):
    favourite_colour = Colour(
        dump_default="#ffffff",
        metadata={"title": "Colour", "description": "Hex RGB"},
    )

For wrapper-style custom fields that need to re-enter the dumping machinery (e.g. to emit a $ref to a recursive schema), declare _jsonschema_type_mapping(self, json_schema, obj) with the two extra parameters and the JSONSchema instance + obj will be passed in.

Polymorphic schemas (marshmallow-oneofschema)

When the optional marshmallow-oneofschema package is installed, dumping a OneOfSchema produces a JSON Schema oneOf over each variant — with the discriminator field pinned to its constant value:

from marshmallow import Schema, fields
from marshmallow_oneofschema import OneOfSchema
from marshmallow_jsonschema import JSONSchema

class TriangleSchema(Schema):
    base = fields.Float(required=True)
    height = fields.Float(required=True)

class CircleSchema(Schema):
    radius = fields.Float(required=True)

class ShapeSchema(OneOfSchema):
    type_schemas = {"triangle": TriangleSchema, "circle": CircleSchema}

JSONSchema().dump(ShapeSchema())

Yields (abbreviated):

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "oneOf": [
    {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "base": {"type": "number", "...": "..."},
        "height": {"type": "number", "...": "..."},
        "type": {"const": "triangle", "type": "string"}
      },
      "required": ["base", "height", "type"]
    },
    { "...circle variant...": "..." }
  ]
}

Variants are inlined (not $ref) so the schema actually validates the wire format OneOfSchema produces. Custom type_field (default "type") is honored. Install with pip install marshmallow-jsonschema[oneofschema].

React-JSONSchema-Form Extension

react-jsonschema-form renders JSON Schema as a React form. It accepts a separate uiSchema that controls presentation; this package's ReactJsonSchemaFormJSONSchema extension dumps both at once:

from marshmallow import Schema, fields
from marshmallow_jsonschema.extensions import ReactJsonSchemaFormJSONSchema

class MySchema(Schema):
    first_name = fields.String(metadata={"ui:autofocus": True})
    last_name = fields.String()

    class Meta:
        react_uischema_extra = {"ui:order": ["first_name", "last_name"]}


json_schema_obj = ReactJsonSchemaFormJSONSchema()
data = json_schema_obj.dump(MySchema())
ui_schema_json = json_schema_obj.dump_uischema(MySchema())

Contributing

Bug reports and pull requests are welcome. See CONTRIBUTING.md for local-dev setup and CONTRIBUTORS.md for the people who built this.

Metadata

Release files for marshmallow-jsonschema 0.16.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for marshmallow-jsonschema 0.16.0
File Size Uploaded Provenance Actions
marshmallow_jsonschema-0.16.0.tar.gz 45.6 kB Without provenance Details for marshmallow_jsonschema-0.16.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for marshmallow-jsonschema 0.16.0
File Interpreter ABI Platform Actions
marshmallow_jsonschema-0.16.0-py3-none-any.whl Python 3 none any Details for marshmallow_jsonschema-0.16.0-py3-none-any.whl

Total release size: 66.0 kB

Release files / marshmallow_jsonschema-0.16.0.tar.gz

Download URL marshmallow_jsonschema-0.16.0.tar.gz
Size 45.6 kB
Tags Source
SHA-256 checksum
How to use checksums
d504ab6156a272d9be850469b2fc4ab3f6e858c3cb66791724afa890dfdee5c8
BLAKE2b-256 checksum
How to use checksums
66a41b0fa2a1658b0b797a60ccbd53c7daa5a37d651016f4aa3e451e9c2955fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.16

Release files / marshmallow_jsonschema-0.16.0-py3-none-any.whl

Download URL marshmallow_jsonschema-0.16.0-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
393b3fd8d73d1d9287c3f65784876c8c14fd41c2553c59a1ea5817d606078105
BLAKE2b-256 checksum
How to use checksums
5ddfe75161abd2fd6624cf280bd2e684104c71b6d4efcc31c80d1286296534b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.16

Security for marshmallow-jsonschema 0.16.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page