marshmallow-jsonschema: JSON Schema formatting with marshmallow
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(withmarshmallow<4)
Client tools that render forms from JSON Schema
- react-jsonschema-form (React; see the extension section below)
- json-editor (vanilla JS; used in
example/example.py)
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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.