Giter Site home page Giter Site logo

fuhrysteve / marshmallow-jsonschema Goto Github PK

View Code? Open in Web Editor NEW
204.0 10.0 73.0 237 KB

JSON Schema Draft v7 (http://json-schema.org/) formatting with marshmallow

License: MIT License

Python 98.07% Makefile 1.93%
marshmallow json-schema marshmallow-jsonschema react-jsonschema-form

marshmallow-jsonschema's Introduction

marshmallow-jsonschema: JSON Schema formatting with marshmallow

Build Status Code style: black

marshmallow-jsonschema translates marshmallow schemas into JSON Schema Draft v7 compliant jsonschema. See http://json-schema.org/

Why would I want my schema translated to JSON?

What are the use cases for this? Let's say you have a marshmallow schema in python, but you want to render your schema as a form in another system (for example: a web browser or mobile device).

Installation

Requires python>=3.6 and marshmallow>=3.11. (For python 2 & marshmallow 2 support, please use marshmallow-jsonschema<0.11)

pip install marshmallow-jsonschema

Some Client tools can render forms using 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()

user_schema = UserSchema()

json_schema = JSONSchema()
json_schema.dump(user_schema)

Yields:

{'properties': {'age': {'format': 'integer',
                        'title': 'age',
                        'type': 'number'},
                'birthday': {'format': 'date',
                             'title': 'birthday',
                             'type': 'string'},
                'username': {'title': 'username', 'type': 'string'}},
 'required': [],
 'type': 'object'}

Nested Example

from marshmallow import Schema, fields
from marshmallow_jsonschema import JSONSchema
from tests import UserSchema


class Athlete(object):
    user_schema = UserSchema()

    def __init__(self):
        self.name = 'sam'


class AthleteSchema(Schema):
    user_schema = fields.Nested(JSONSchema)
    name = fields.String()

    
athlete = Athlete()
athlete_schema = AthleteSchema()

athlete_schema.dump(athlete)

Complete example Flask application using brutisin/json-forms

Screenshot

This example renders a form not dissimilar to how wtforms might render a form.

However rather than rendering the form in python, the JSON Schema is rendered using the javascript library brutusin/json-forms.

from flask import Flask, jsonify
from marshmallow import Schema, fields
from marshmallow_jsonschema import JSONSchema

app = Flask(__name__)


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


@app.route('/schema')
def schema():
    schema = UserSchema()
    return jsonify(JSONSchema().dump(schema))


@app.route('/')
def home():
    return '''<!DOCTYPE html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/brutusin.json-forms/1.3.0/css/brutusin-json-forms.css"><Paste>
<script src="https://code.jquery.com/jquery-1.12.1.min.js" integrity="sha256-I1nTg78tSrZev3kjvfdM5A5Ak/blglGzlaZANLPDl3I=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.string/3.3.4/underscore.string.min.js"></script>
<script src="https://cdn.jsdelivr.net/brutusin.json-forms/1.3.0/js/brutusin-json-forms.min.js"></script>
<script>
$(document).ready(function() {
    $.ajax({
        url: '/schema'
        , success: function(data) {
            var container = document.getElementById('myform');
            var BrutusinForms = brutusin["json-forms"];
            var bf = BrutusinForms.create(data);
            bf.render(container);
        }
    });
});
</script>
</head>
<body>
<div id="myform"></div>
</body>
</html>
'''


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

Advanced usage

Custom Type support

Simply add a _jsonschema_type_mapping method to your field so we know how it ought to get serialized to JSON Schema.

A common use case for this is creating a dropdown menu using enum (see Gender below).

class Colour(fields.Field):

    def _jsonschema_type_mapping(self):
        return {
            'type': 'string',
        }

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

class Gender(fields.String):
    def _jsonschema_type_mapping(self):
        return {
            'type': 'string',
            'enum': ['Male', 'Female']
        }


class UserSchema(Schema):
    name = fields.String(required=True)
    favourite_colour = Colour()
    gender = Gender()

schema = UserSchema()
json_schema = JSONSchema()
json_schema.dump(schema)

React-JSONSchema-Form Extension

react-jsonschema-form is a library for rendering jsonschemas as a form using React. It is very powerful and full featured.. the catch is that it requires a proprietary uiSchema to provide advanced control how the form is rendered. Here's a live playground

(new in version 0.10.0)

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()
schema = MySchema()

# here's your jsonschema
data = json_schema_obj.dump(schema)

# ..and here's your uiSchema!
ui_schema_json = json_schema_obj.dump_uischema(schema)

marshmallow-jsonschema's People

Contributors

abcdenis avatar alkanen avatar atmo avatar avilaton avatar benmotz avatar corey-biarri avatar coreydexter avatar ecarreras avatar eligundry avatar erik avatar fuhrysteve avatar ghostwheel42 avatar hadasarik avatar hf-kklein avatar hjc avatar jacksontoomey avatar jbryan avatar kaos avatar martijnthe avatar mouadino avatar mrcljx avatar noamkush avatar nusnuson avatar sdayu avatar sidrubs avatar sloria avatar stepland avatar stringfellow avatar xlevus avatar yeralin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

marshmallow-jsonschema's Issues

Extension for custom (enum) types?

Hey there,

I'm using marshmallow in combination with data class extension by @lovasoa and the enum extension by @justanr to create a json schema from my data class.

Unfortunately, this does not work out of the box. The JSON Schema runs into errors when building the schema.

So I derived it to a EnumSupportingJSONSchema like this.

class _EnumSupportingJSONSchema(JSONSchema):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def _get_python_type(self, field):
        if issubclass(field.__class__, EnumField):
            return field.enum

        return super(_EnumSupportingJSONSchema, self)._get_python_type(field)
    
    def _from_python_type(self, obj, field, pytype):
        if issubclass(field.__class__, EnumField):
            PY_TO_JSON_TYPES_MAP[pytype] = { "type" : "string" }
            PY_TO_JSON_TYPES_MAP[pytype]["enum"] = [ value.name for value in pytype ]
        return super(_EnumSupportingJSONSchema, self)._from_python_type(obj, field, pytype)

This works fine. Unfortunately the ruby-like part where I extend the singleton class looks crappy.

What I would like to suggest is to use a per-instance dictionary of maps, which is initialized from the global dictionaries.

This way, it would be possible to sub-class this this way:

class _EnumSupportingJSONSchema(JSONSchema):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def _get_python_type(self, field):
        if issubclass(field.__class__, EnumField):
            enum_type = field.enum
            self.map(enum_type, { "type": "string", "enum": [ value.name for value in enum_type ] })
            return enum_type

        return super(_EnumSupportingJSONSchema, self)._get_python_type(field)

This way, the mapping would be only for the current instance and the JSONSchema is not "poisoned" by using optional values.

What do you think of my suggestion?

Shouldn't we treat marshmallow-jsonschema as a kind of marshmallow schema?

Marshmallow is a object serialization library. And also, marshmallow-jsonschema serializes(dumps) a form which.
So, in my opinion, marshmallow-jsonschema should be made as a kind of marshmallow schema. This schema will be schema of schema.

The API would be like this

>>> json_schema = JSONSchema()
>>> user_schema = UserSchema()
>>> result = json_schema.dump(user_schema)
>>> result.data
{'properties': {'addresses': ...

Marshmallow-mongoenine support

Are there any plans to support Marshmallow-Mongoengine ModelSchema feature, which will automatically create a base schema from a model?

I've been using the convenience of Marshmallow-Mongoengine to avoid having to recreate lengthy models into schemas (DRY), but would also to like to use marshmallow-jsonschema.

The basic errors I've receive so far are "unsupported field type <fields.ObjectId>" and "<fields.ReferenceField>". All works fine if I manually create the schemas.

Deeply nested schemas - how to construct into JSONSchema?

Say I have a deeply nested schema like this:


class D(Schema):
    f = fields.Int()

class C(Schema):
    e = fields.Str()

class B(Schema):
    c = fields.Nested(C)
    d = fields.Nested(D)

class A(Schema):
    b = fields.List(
        fields.Nested(B)
    )

How, when serialising A() with JSONSchema do you get the full representation (ultimately for use with brutusin-jsonforms)? At the moment it doesn't seem to automatically construct the inner schemas with JSONSchema - am I missing something?

field defined for a List not represented in the jsonschema

I got this marshmallow schema that defines a list of URL's:

class SelectionSchema(Schema):
    selection = fields.List(fields.URL(required=True), required=True, validate=validate.Length(min=1))

But when I generate the json version I get the following, note there is no mention of the field type inside the list:

{
    "required": [
        "selection"
    ],
    "properties": {
        "selection": {
            "title": "selection",
            "type": "array",
            "minItems": 1
        }
    },
    "type": "object"
}

Is this expected behaviour? I'd expect the "selection" element to have an "items" element with a schema.

This is on python 3.6 and marshmallow 2.13.5

UnsupportedValueError on marshmallow.fields.Number

Recently I noticed that marshmallow-jsonschema does not work with marshmallow.fields.Number field and raises UnsupportedValueError.

Is there a particular reason why it does not? It works well with marshmallow.fields.Integer. Maybe we should just map it to Integer?

Nested field allow_none=True is not considered in definitions

    class ChildSchema(Schema):
        id = fields.Integer(required=True)

    class TestSchema(Schema):
        id = fields.Integer(required=True)
        nested_fld = fields.Nested(ChildSchema, allow_none=True)

    schema = TestSchema()

    dumped = validate_and_dump(schema)

should result on a schema that allows the nested_fld to either conform to ChildSchema or to be None.

0.5.0 release?

There's some stuff in master that's not on pypi - also PR #39 has a build fail which I think is just a travis blip - could it be re-built and merged if acceptable?

oneOf and anyOf support?

Just barely looked at the code but I didn't find mentions of oneOf and anyOf.

Any plans to implement?

Support for validators like OneOf

"One of" (or valid values lists) seem to be present in the JSONSchema spec but don't seem to be recognised by marshmallow-jsonschema

Example:

class TestSchema(Schema):
    a = fields.String()
    b = fields.Integer(default=456)
    c = fields.List(
        fields.Integer,
        validate=validate.OneOf(choices=[9, 8, 7])
    )

dumped = JSONSchema().dump(TestSchema()).data

pp dumped

{u'properties': {'a': {'title': 'a', 'type': 'string'},
                 'b': {'default': 456,
                       'format': 'integer',
                       'title': 'b',
                       'type': 'number'},
                 'c': {'title': 'c', 'type': 'array'}},
 u'required': [],
 u'type': 'object'}

Calling json_schema.dump(schema) with Nested throws error

Hi,

I've declared all nested objects in a schema using string instead of class and when json_schema.dump(schema) is executed, an error TypeError: 'str' object is not callable is raised.
For example:

class TaskExecuteRequestSchema(Schema):
    """ JSON schema for executing tasks """
    id = fields.Integer(required=True)
    order = fields.Integer(required=True)
    log_level = fields.String(required=True)
    is_start = fields.Boolean(required=True)
    is_end = fields.Boolean(required=True)
    operation_id = fields.Integer(required=True)
    operation_name = fields.String(required=True)
    next_task_id = fields.Integer()
    input = fields.Nested('DataSourceExecuteRequestSchema',
                          required=True)
    output = fields.Nested('DataSourceExecuteRequestSchema',
                           required=True)
    parameters = fields.Nested('KeyValuePairExecuteRequestSchema',
                               required=True,
                               many=True)

If I remove single quotes from names, it works.
I suggest changing marshmallow_jsonschema/base.py, line 147, to test if in this line: schema = cls().dump(field.nested()).data, field.nested is callable or not.

Thanks

Range Validation Incorrect?

if validator.min:
schema['minimum'] = validator.min
schema['exclusiveMinimum'] = True
else:
schema['minimum'] = 0
schema['exclusiveMinimum'] = False
if validator.max:
schema['maximum'] = validator.max
schema['exclusiveMaximum'] = True

According to
the docs, marshmallow wants max and min to be inclusive (so exclusiveMinimum should always be False, which is the default). Also, minimum should be set only when present in the validator rather than being set to 0. Is there a reason this code deviates from the standards in this way?

Marshmallow v3 Support

I found that Marshmallow 3 (pre-release) removed the .data,.error notation from the Marshall/UnMarshall classes, which is referenced in this code base.

JSONSchema().dump(schema) does not support allow_none in schema

If I have the following:

class mySchema(Schema): id = Int(allow_none=True)

JSONSchema().dump(mySchema) will return 'id': {'title': 'id', 'type': 'number', 'format': 'integer'} but will not specify that it can be None. As a result, when it is None, I get a None is not of type 'number' error.

Where is 0.7.0?

It is distributed in pypi, yet it's nowhere to be seen on master.

There are a bunch of branches, none of them explicitly related to 0.7.0, so where does that pypi version come from?

Wrong types in JSON

I specified the model as:

class TestRoleSchema(db_schema.SQLAlchemyAutoSchema):
    class Meta:
        model = Role

If I have the datetime field, the result JSON will be:

created:
format: "date-time"
title: "created"
type: "string"

The question is why the type is string when the original type is Date? Are there any specifications on data types?

Also, for boolean the type is presented as an array:

is_test_data:
{  title: "is_test_data"
   type: Array(2)
   0: "boolean"
   1: "null"}

Mark fields as read only when using dump_only

marshmallow allows marking fields with dump_only / load_only, it would be good to know fields that have been marked as such. Do you think this would require adding another field to JSONSchema, e.g. read_only / write_only?

Incorrect integer type

fields.Integer should produce a JSON schema with "type": "integer" as per https://json-schema.org/understanding-json-schema/reference/numeric.html?highlight=integer#integer . However, a schema with "type": "number", "format": "integer" is produced. The number docs do not mention integer as a format and AFAIK JSON schema validators will not perform the intended integer validation.

This behaviour is defined by:

int: {"type": "number", "format": "integer"},

Related (I think) issue: #40

Failing Test Case

diff --git a/tests/test_dump.py b/tests/test_dump.py
index ee63cda..02a191c 100644
--- a/tests/test_dump.py
+++ b/tests/test_dump.py
@@ -1,10 +1,32 @@
 import pytest
+import jsonschema
 from marshmallow import Schema, fields, validate
 
 from marshmallow_jsonschema import JSONSchema, UnsupportedValueError
+
 from . import UserSchema, validate_and_dump
 
 
+class TestIntegerField:
+    class Foo(Schema):
+        bar = fields.Integer()
+
+    def test_schema_type(self):
+        schema = JSONSchema().dump(self.Foo())
+        bar_property = schema["definitions"]["Foo"]["properties"]["bar"]
+
+        assert bar_property["type"] == "integer"
+        assert "format" not in bar_property
+
+    def test_validation(self):
+        schema = JSONSchema().dump(self.Foo())
+
+        jsonschema.validate({"bar": 1}, schema)
+
+        with pytest.raises(jsonschema.ValidationError):
+            jsonschema.validate({"bar": 1.1}, schema)
+
+
 def test_dump_schema():
     schema = UserSchema()

I'm happy to submit a PR for this if an appropriate course of action is agreed upon ๐Ÿ˜„

JSON Schema generation raises UnsupportedValueError on marshmallow.fields.* subclasses

Hi,

I have a rather unusual problem. I have a wrapper on top of marshmallow.fields.* classes. Something similar to:

from marshmallow.fields import String

class CustomString(String):
    ...

When I try to generate a JSON schema that contains one of those wrapped fields like CustomString, the generator raises UnsupportedValueError. After looking at the code, I noticed this line:
https://github.com/fuhrysteve/marshmallow-jsonschema/blob/master/marshmallow_jsonschema/base.py#L158

Where my field.__class__ resolves to CustomString while mapping contains marshmallow.fields.String.

That was a bummer. I wrote a quick PR for this issue that instead checks whether field's class is a subclass of one of the marshmallow.fields.*.

Feel free to share your thoughts about it!

Thank you! โค๏ธ

Metadata is not serialized (only description and title are)

Using the example from https://github.com/mozilla-services/react-jsonschema-form#multiple-choices-list -- it should be possible to set the uniqueItems property of a field. A simple way to allow extra metadata like this is to build on the support in Marshmallow for kwargs to be set in the metadata. In a previous issue, the field kwargs were added to the metadata (#39) but these were never serialized out. (So effectively useless except for description and title).

Ability to modify JSON schema property name

Hi,

I have a problem with marshmallow-jsonschema where during the translation it uses field names rather that schema attributes.

For example, I have a following schema:

class ExampleSchema(Schema):
    api_token = String(attribute='api-token', required=True,
                       description='API token.')

If I run JSONSchema().dump(ExampleSchema()).data, it will translate to:

{
    "$ref": "#/definitions/LoginTokenRequestSchema",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "ExampleSchema": {
            "additionalProperties": false,
            "properties": {
                "api_token": {
                    "description": "API token.",
                    "title": "api-token",
                    "type": "string"
                }
            },
            "required": [
                "api_token"
            ],
            "type": "object"
        }
    }
}

As you can see, it used the field name (ExampleSchema.api_token) from the schema instead of its attribute (api-token). attribute='api-token' was used for title in the resulting JSON schema.

Originally in the marshmallow core, attribute parameter is utilized for marshaling: https://marshmallow.readthedocs.io/en/2.x-line/quickstart.html#specifying-attribute-names

In my case, I'm just trying to follow PEP8 having lower_case_with_underscores variable names in the python code, but then in the resulting JSON schema I would want to follow camelCase. I was hoping to achieve that specifying attribute parameter.

Is there some kinda parameter I could pass to JSONSchema to pick schema's attribute instead?

Why is field.Raw resulting in type: string?

Hi, we noticed that on the fields in our schemas that use fields.Raw, a string jsonschema type is returned and we expected an object type, is this expected or should we attempt to correct this?

Don't Blindly Try to Construct Schemas

So, if you have a Nested field that you pass a schema you've already constructed, marshmallow-jsonschema fails with the following error:

  File "~/.env/local/lib/python2.7/site-packages/marshmallow_jsonschema/base.py", line 147, in _from_nested_schema
    schema = cls().dump(field.nested()).data
TypeError: 'LastAttachmentSchema' object is not callable

This is what the code for that Nested field looks like:

class ThreadPaginatedSchema(ThreadSchema):
    """Schema for paginated threads"""
    last_attachments = fields.Nested(
        LastAttachmentSchema(context={'child': True}), many=True
    )   

    class Meta(object):
        """Keys to remove"""
        exclude = ('project_id',)

We need to construct the schema so we can update it's context and JUST it's context (because setting a context of child=True on the parent won't work). Looking at Marshmallow's Nested field, they do handle this usecase. Should be as simple as adding an isinstance check around the line that errors.

Handling unknown typed field.

Marshmallow provides a method to making custom field. But they don't specify output data's type.
So it is not able to dump them.

Suppose we have custom field like following

class Colour(fields.Field):
    def _serialize(self, value, attr, obj):
        r, g, b = value
        r = hex(r)[2:]
        g = hex(g)[2:]
        b = hex(b)[2:]
        return '#' + r + g + b

And we have schema like following.

class UserSchema(Schema):
    name = fields.String(required=True)
    favourite_colour = Colour()

We cannot assume the type of field favourite_colour.

We may can add type to arbitrary field by providing wrapper field.

class UserSchema(Schema):
    name = fields.String(required=True)
    favourite_colour = StringTyped(Colour())

Should `dump_schema` be an instance method of a schema?

We may want to avoid imposing a BaseJsonSchema (unless we use mixins, which also seem like something we should avoid unless there are compelling reasons to) since Marhmallow-sqlalchemy uses them and this library needs to be compatible with that library.

However, I'm struggling to think of another way to inject this functionality into marshmallow without doing something funky like monkey patching.

Maybe we could suggest a metaclass sort of plugin system in marshmallow?

Mixin style

from marshmallow_sqlalchemy import ModelSchema
from marshmallow_jsonschema import JSONSchemaMixin
from .models import Book  # some sqlalchemy model

class BookSchema(ModelSchema, JSONSchemaMixin):
    class Meta:
        model = Book

bs = BookSchema()
bs.jsonschema()

Metaclass "plugin" style

from marshmallow import register_plugin  # this doesn't actually exist
from marshmallow_jsonschema import JSONSchemaPlugin
register_plugin(JSONSchemaPlugin)

from marshmallow_sqlalchemy import ModelSchema
from .models import Book  # some sqlalchemy model

class BookSchema(ModelSchema):
    plugins = ['jsonschema']
    class Meta:
        model = Book

bs = BookSchema()
bs.jsonschema()

AttributeError: 'dict' object has no attribute 'data' on on List of Nested fields

I get 'dict' object has no attribute 'data' when i try to generate JSON schema for a model which contains List of Nested fields, here is an example of broken code:

        class User(Schema):
            f1 = fields.Integer()

        class UserList(Schema):
            f2 = fields.List(fields.Nested(User))


        JSONSchema().dump(UserList())

Python 3.6.4
marshmallow==3.0.0b11
marshmallow-jsonschema==0.5.0

Tests Through setup.py Aren't Working

I tried running tests against the latest master and they seem to be broken. Here is my shell output:

$ python setup.py test
running test
Searching for marshmallow>=2.9.0
Best match: marshmallow 2.9.1
Processing marshmallow-2.9.1-py2.7.egg

Using /home/eligundry/Code/marshmallow-jsonschema/.eggs/marshmallow-2.9.1-py2.7.egg
Searching for coverage>=4.1
Best match: coverage 4.2
Processing coverage-4.2-py2.7-linux-x86_64.egg

Using /home/eligundry/Code/marshmallow-jsonschema/.eggs/coverage-4.2-py2.7-linux-x86_64.egg
Searching for strict-rfc3339
Best match: strict-rfc3339 0.7
Processing strict_rfc3339-0.7-py2.7.egg

Using /home/eligundry/Code/marshmallow-jsonschema/.eggs/strict_rfc3339-0.7-py2.7.egg
Searching for jsonschema
Best match: jsonschema 2.5.1
Processing jsonschema-2.5.1-py2.7.egg

Using /home/eligundry/Code/marshmallow-jsonschema/.eggs/jsonschema-2.5.1-py2.7.egg
Searching for functools32
Best match: functools32 3.2.3.post2
Processing functools32-3.2.3.post2-py2.7.egg

Using /home/eligundry/Code/marshmallow-jsonschema/.eggs/functools32-3.2.3.post2-py2.7.egg
running egg_info
writing requirements to marshmallow_jsonschema.egg-info/requires.txt
writing marshmallow_jsonschema.egg-info/PKG-INFO
writing top-level names to marshmallow_jsonschema.egg-info/top_level.txt
writing dependency_links to marshmallow_jsonschema.egg-info/dependency_links.txt
reading manifest file 'marshmallow_jsonschema.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'marshmallow_jsonschema.egg-info/SOURCES.txt'
running build_ext

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

It looks like the tests_suite variable is set correctly so I dunno what's up. I could also completely be doing it wrong. As an aside, there is nothing in the readme saying how to run the tests.

Respect order given by OrderedDict

When using

class Meta:
    ordered = True

in schemas, the fields are already ordered. marshmallow-jsonschema always uses sorted(...), discarding the order that was present.

There are some ways to go about this, do you have some preference? One way would be checking for ordered dicts before running sorted(...).

props_ordered does not work for nested fields

Hi everyone,

We are using marshmallow-jsonschema to generate a JSON schema for json-editor.
I noticed that the recently introduced props_ordered argument does not work for nested schemas.

Extended Test Case:

def test_sorting_properties():

	class NestedTestSchema(Schema):
		class Meta:
			ordered = True

		z = fields.Str()
		y = fields.Str()

	class TestSchema(Schema):
		class Meta:
			ordered = True

		d = fields.Str()
		c = fields.Str()
		a = fields.Str()
		l = fields.Nested(NestedTestSchema)

	# Should be sorting of fields
	schema = TestSchema()

	json_schema = JSONSchema()
	dumped = json_schema.dump(schema)
	data = dot_data_backwards_compatible(dumped)

	sorted_keys = sorted(data["definitions"]["TestSchema"]["properties"].keys())
	properties_names = [k for k in sorted_keys]
	assert properties_names == ["a", "c", "d", "l"]

	sorted_keys = data["definitions"]["NestedTestSchema"]["properties"].keys()
	properties_names = [k for k in sorted_keys]

	assert properties_names == ["y", "z"]

	# Should be saving ordering of fields
	schema = TestSchema()
	json_schema = JSONSchema(props_ordered=True)
	dumped = json_schema.dump(schema)
	data = dot_data_backwards_compatible(dumped)

	keys = data["definitions"]["TestSchema"]["properties"].keys()
	properties_names = [k for k in keys]

	assert properties_names == ["d", "c", "a", "l"]

	keys = data["definitions"]["NestedTestSchema"]["properties"].keys()
	properties_names = [k for k in keys]
        # FIXME: Not ordered
	assert properties_names == ["z", "y"]

Support for using load_from or dump_to as field titles

JSONSchema should support to use of load_from or dump_to (or the equivalent in marshmallow 3)

for example:

class CampaignCompletion(Schema):

    id_ = fields.UUID(load_from='id', dump_to='id') 
    version = fields.Integer()
    timestamp = fields.DateTime()
    campaign_name = fields.String(load_from='campaignName', dump_to='campaignName')

Currently this dumps to

{
    "definitions": {
        "CampaignCompletion": {
            "properties": {
                "campaign_name": {
                    "title": "campaign_name",
                    "type": "string"
                },
                "id_": {
                    "title": "id_",
                    "type": "string",
                    "format": "uuid"
                },
                "timestamp": {
                    "title": "timestamp",
                    "type": "string",
                    "format": "date-time"
                },
                "version": {
                    "title": "version",
                    "type": "number",
                    "format": "integer"
                }
            },
            "type": "object",
            "required": []
        }
    },
    "$ref": "#/definitions/CampaignCompletion"
}

In this case, the correct json schema of our model is the one that represents the serialized object, not the python dictionary/object behind the schema. So

{
    "definitions": {
        "CampaignCompletion": {
            "properties": {
                "campaignName": {
                    "title": "campaignName",
                    "type": "string"
                },
                "id": {
                    "title": "id",
                    "type": "string",
                    "format": "uuid"
                },
                "timestamp": {
                    "title": "timestamp",
                    "type": "string",
                    "format": "date-time"
                },
                "version": {
                    "title": "version",
                    "type": "number",
                    "format": "integer"
                }
            },
            "type": "object",
            "required": []
        }
    },
    "$ref": "#/definitions/CampaignCompletion"
}

Dump partial loading schema still return required fields.

Hi everyone,

Thank @fuhrysteve for this awesome lib.

As using the lib, I find out that schema with partial loading does not parse correctly to JSON schema. It still has required fields even though it should not. Here is the example test.

from marshmallow import Schema, fields
from marshmallow_jsonschema import JSONSchema


class UserSchema(Schema):
    name = fields.String(required=True)
    email = fields.String(required=True)


schema = UserSchema(partial=True)

assert schema.load({}) == {}

required_fields = JSONSchema().dump(schema)['definitions']['UserSchema']['required']

print(required_fields)  # ['email', 'name']
assert required_fields == []

Expected results

  • The assertion test should run correctly.

Current results

  • required_fields has values email and name.

I'm happy to investigate and make PR to this issue.

Cannot generate top level array schemas

Consider following schema:

from marshmallow import Schema, fields

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

Now, say my payload is of this form:

[{"username": "test-1", "age": 1}, {"username": "test-2", "age": 2}]

The JSON Schema that could describe this payload could be:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array", <- important part
  "definitions": {
      "UserSchema": {
        "items": {
            "properties": {
              "username": {
                "type": "string",
                "title": "username"
              },
              "age": {
                "type": "number",
                "format": "integer"
                "title": "age"
              }
            }
          }
      }
  }
}

So, in theory to generate this schema using marshmallow-jsonschema we could do the following:

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

However, that's not the case. The resulting schema would be:

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

Setting many=True during schema instantiation does not affect the resulting JSON schema. According to

type = fields.Constant("object")

It will always be set to "type": "object" irregardless of many option.

Wrong type serialization

If I have the datetime field, the result JSON will be:

created:
format: "date-time"
title: "created"
type: "string"

Also, for boolean the type is presented as an array:

is_test_data:
{  title: "is_test_data"
   type: Array(2)
   0: "boolean"
   1: "null"}

Incompatible with marshmallow==3.0.0rc9

marshmallow-jsonschema works fine with marshmallow<=3.0.0rc8, however, due to the removal of marshmallow.fields.LocalDateTime as noted in the changelog, this line now fails:

fields.LocalDateTime: datetime.datetime,

As a side note, Schema.dump() now returns data directly, it's no longer a tuple, meaning that your examples won't work anymore after the next release

I'm not sure if it's ok for me to open the issue as this is a future release, but I wanted to let you know before it happens (and it seems it's going to be soon ๐Ÿ‘ )

0.4.0 release?

You made a fix about nested fields being strings which is not yet released, can we get that released?

support data_key

we have some schema using unqualified names like 2019, 1abc, we use data_key to support it

class A(Schema):
  a = fields.String(data_key='2019')

we would like it to be dumped as

{'2019': {'title': '2019', 'type': 'string'}

it's now dumped as

{'a': {'title': 'a', 'type': 'string'}

schema produced for an integer field breaks react-jsonschema-form

I've created a marshmallow schema with an integer field. This library generates JSON schema for the field as:

    "id": {
      "format": "integer",
      "title": "id",
      "type": "number"
    },

When I feed that schema to the Form React component from https://github.com/mozilla-services/react-jsonschema-form, I get an error:

Error: No widget "integer" for type "number"

Based on their examples and my limited reading of the JSON Schema spec, maybe the correct JSON schema should be:

    "id": {
      "title": "id",
      "type": "integer"
    },

Doubly nested list schema generates null title

Singly nested schema list like:

class TestSchema(Schema):
    test = List(Integer()))

Works just fine:

{
    "$ref": "#/definitions/TestSchema",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "TestSchema": {
            "additionalProperties": false,
            "properties": {
                "test": {
                    "items": {
                        "format": "integer",
                        "title": "test", <- title is assigned w/o any problems
                        "type": "number"
                    },
                    "title": "test",
                    "type": "array"
                }
            },
            "type": "object"
        }
    }
}

But if you add another level of nestness, it will start generating null values for titles which doesn't conform to JSON Schema specifications. To reproduce:

from marshmallow import Schema
from marshmallow.fields import List, Integer
from marshmallow_jsonschema import JSONSchema
import json

class TestSchema(Schema):
    test = List(List(Integer()))

test_schema = TestSchema()
json_schema = JSONSchema()
print(json.dumps(json_schema.dump(test_schema).data, indent=4))

Will yield:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "TestSchema": {
            "type": "object",
            "properties": {
                "test": {
                    "title": "test",
                    "type": "array",
                    "items": {
                        "title": "test",
                        "type": "array",
                        "items": {
                            "title": null, <- problem
                            "type": "number",
                            "format": "integer"
                        }
                    }
                }
            },
            "additionalProperties": false
        }
    },
    "$ref": "#/definitions/TestSchema"
}

ModuleNotFoundError: No module named 'marshmallow.compat' with marshmallow 3.0.0rc6 installed

Executing the JSONSchema example

from marshmallow import Schema, fields
from marshmallow_jsonschema import JSONSchema
class UserSchema(Schema):
    username = fields.String()
    age = fields.Integer()
    birthday = fields.Date()
user_schema = UserSchema()
json_schema = JSONSchema()
json_schema.dump(user_schema).data

with marshmallow 3.0.0rc6 installed yields

ModuleNotFoundError: No module named 'marshmallow.compat'

AFAIS the module marshmallow.compat is gone with version 3.0.0. (cf. file finder)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.