flask-restplus
flask-restplus copied to clipboard
JSON Schema $ref not working (not even the doc example)
Using the JSON Schema example (http://flask-restplus.readthedocs.io/en/stable/marshalling.html#define-model-using-json-schema)
Address object looks like it's recognized but not much more. This is on 0.10.1

This is a stopper for me right now. Any workaround / ideas?
I haven't found a solution for this yet. Does anyone have a clue?
What's the expected behavior? Can you post your full code?
Expected behavior would be that 'address' is showing in the Example box. It's completely absent right now. It should also show the fields under Address in the Model box. I have attached a very simple example where the same models are defined with JSON Schema and Fields. They should be identical in swagger doc.
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask
from flask_restplus import Api, Resource, fields
import json
app = Flask(__name__)
api = Api(app)
# Fields model is working as expected.
f_address = api.model('Address_', {
'road': fields.String()
})
f_person = api.model('Person_', {
'name': fields.String(),
'age': fields.Integer(),
'birthday': fields.DateTime(),
'address': fields.Nested(f_address)
})
# The code below are directly from http://flask-restplus.readthedocs.io/en/stable/marshalling.html#define-model-using-json-schema
address = api.schema_model('Address', {
'properties': {
'road': {
'type': 'string'
},
},
'type': 'object'
})
person = address = api.schema_model('Person', {
'required': ['address'],
'properties': {
'name': {
'type': 'string'
},
'age': {
'type': 'integer'
},
'birthdate': {
'type': 'string',
'format': 'date-time'
},
'address': {
'$ref': '#/definitions/Address',
}
},
'type': 'object'
})
# One route for each model
@api.route('/addressfields')
class AddressFields(Resource):
@api.expect(f_person)
def get(self):
return 200
@api.route('/addressjson')
class AddressJson(Resource):
@api.expect(person)
def get(self):
return 200
if __name__ == '__main__':
app.run(debug=True)
Is there no solution to this?
I also haven't been able to use JSONschema.
I can't document my nested models, and using @ns.expect fails validation for nested required fields.
Same problem. Looks like this issue is a year old at this point. Following the example for complex and nested structures seems to result in this issue. The error is rather cryptic. Can you just drop support for nested and complex structures completely? I'd rather not be lead to believe this is a feature when it doesn't work.
This is a long standing problem in Flask-restplus and the only solution is to use JSON schema models instead of trying to use nested flask-restplus models at which point you might as well use another marshalling/validation library altogether.
Anyone has a solution to register the '$ref' for a SchemaModel as another SchemaModel created from JSONSchema? I need to properly display in the Swagger documentation in browser without errors and to show all the models in the list. I'm also looking for workarounds if any: One could be register models in dummy namespace, at least the model will be shown. Another would be to expand the $ref before registering the JsonSchema,
After investigating it looks to me that the issue is in swagger.py function def register_model(self, model) Line 511, it doesn't check the SchemaModel. The fix should be added in the file. register_model and register_field, if I can find a solution, I will gladly share it with you.
I have added a quick fix here: https://github.com/tincumagic/flask-restplus/commit/469e4c063f5362ef16a9ebc505e1223083e2bc17 At least for my cases it works as I want and also for the example in documentation with Address and Person. http://flask-restplus.readthedocs.io/en/stable/marshalling.html#define-model-using-json-schema
Thanks a lot for the hot fix - works for me!
Guys please help me push my fix inside the library flask-restplus. It realy works and helps documenting, the ref elemets that without the fix only show None
Possible workaround: Use the jsonref library to load and dereference your schemas before passing them to api.schema_model(). I'm using this primarily because I've my json schemas stored in separate files.
import jsonref
jsonref_schema = jsonref.loads('''
{
"definitions": {
"fruit": {
"type": "string"
}
},
"id": "apple",
"allOf": [
{ "$ref": "#/definitions/fruit" }
]
}
''')
# copy.deepcopy is a workaround for a problem with jsonref's lazy loading together with flask non-debug (production) mode.
# It would produce a JSON serialisation error otherwise.
apple_input = api.schema_model('Apple POST input', copy.deepcopy(jsonref_schema))
Pay attention to the copy step before using the jsonref object. jsonref lazy laods the references. In flask debug mode this works fine but in production environment the swagger.json generation will fail with 'TypeError: Object of type dict is not JSON serializable'.
@siddharthist could you merge the fix? if there have something need to do, please comment here. I find some check is error "coverage/coveralls — Coverage decreased (-0.5%) to 96.329% Details"
I've checked on pr-555. It needs a rebase and tests added for the new functionality. I commented on the PR, and i'm checking things myself as well.
After reviewing pr-555, it does not work to solve the case in my setup after a rebase. It fails to do the nested lookup properly on resolution. It appears to still not respect the nesting
I've tried using jsonref as @jojoob mentioned, and this is working for me. It appears to be the best current workaround. This does remove the abstraction, so you lose some nice documentation of the separate models.
I am seeing some oddness with what gets displayed still once i get a few levels deep. I'll need to do some more checking to see what's up.
i just had to do the jsonref fix myself. would be nice not to have to go thru the extra step