noirbizarre / flask-restplus

Fully featured framework for fast, easy and documented API development with Flask
http://flask-restplus.readthedocs.org
Other
2.73k stars 507 forks source link

Using nested JSON schemata for marshalling #414

Open Midnighter opened 6 years ago

Midnighter commented 6 years ago

Hi,

In my application I would like to generate models for marshalling from JSON schema. The problem I run across is that flask-restplus does not seem to be aware of the whole JSONSchema spec. Specifically, I have the following schema:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Plasmids Serialization Schema",
  "type": "object",
  "required": [
    "plasmids"
  ],
  "properties": {
    "plasmids": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/Plasmid"
      },
      "uniqueItems": true
    }
  },
  "additionalProperties": false
}

The error I get is then:

File "x/lib/python3.6/site-packages/flask/app.py", li
ne 1612, in full_dispatch_request                                                             
    rv = self.dispatch_request()                                                              
  File "x/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request                   
    return self.view_functions[rule.endpoint](**req.view_args)                                
  File "x/lib/python3.6/site-packages/flask_restplus/ap
i.py", line 313, in wrapper                                                                   
    resp = resource(*args, **kwargs)                                                          
  File "x/lib/python3.6/site-packages/flask/views.py", 
line 84, in view                                                                              
    return self.dispatch_request(*args, **kwargs)                                             
  File "x/lib/python3.6/site-packages/flask_restplus/re
source.py", line 44, in dispatch_request
    resp = meth(*args, **kwargs)
  File "x/lib/python3.6/site-packages/flask_restplus/ma
rshalling.py", line 110, in wrapper
    return marshal(resp, self.fields, self.envelope, mask)
  File "x/lib/python3.6/site-packages/flask_restplus/ma
rshalling.py", line 54, in marshal
    for k, v in fields.items())
AttributeError: 'SchemaModel' object has no attribute 'items'

Of course, my model has no attribute 'items' since that is only the specification of the "plasmids" array. I have checked all my schemata against the Draft4Validator and they're fine. Am I using it in the wrong way within flask-restplus?

with open_text(sanger_service.schemata, "plasmid.json",
               encoding="utf-8") as file_handle:
    plasmid = api.schema_model('Plasmid', json.load(file_handle))

with open_text(sanger_service.schemata, "plasmids.json",
               encoding="utf-8") as file_handle:
    plasmids = api.schema_model('Plasmids', json.load(file_handle))

@api.marshal_with(plasmids)
...

I'm using Python 3.6 and flask-restplus 0.10.1.

Colin-b commented 6 years ago

Can't you use plasmid and as_list=True (or something similar) as second optional parameter for marshalling decorator ?

On Wed, Mar 28, 2018, 12:37 Moritz E. Beber notifications@github.com wrote:

Hi,

In my application I would like to generate models for marshalling from JSON schema. The problem I run across is that flask-restplus does not seem to be aware of the whole JSONSchema spec. Specifically, I have the following schema:

{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "Plasmids Serialization Schema", "type": "object", "required": [ "plasmids" ], "properties": { "plasmids": { "type": "array", "items": { "$ref": "#/definitions/Plasmid" }, "uniqueItems": true } }, "additionalProperties": false }

The error I get is then:

File "x/lib/python3.6/site-packages/flask/app.py", li ne 1612, in full_dispatch_request rv = self.dispatch_request() File "x/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request return self.view_functionsrule.endpoint File "x/lib/python3.6/site-packages/flask_restplus/ap i.py", line 313, in wrapper resp = resource(*args, kwargs) File "x/lib/python3.6/site-packages/flask/views.py", line 84, in view return self.dispatch_request(*args, *kwargs) File "x/lib/python3.6/site-packages/flask_restplus/re source.py", line 44, in dispatch_request resp = meth(args, kwargs) File "x/lib/python3.6/site-packages/flask_restplus/ma rshalling.py", line 110, in wrapper return marshal(resp, self.fields, self.envelope, mask) File "x/lib/python3.6/site-packages/flask_restplus/ma rshalling.py", line 54, in marshal for k, v in fields.items()) AttributeError: 'SchemaModel' object has no attribute 'items'

Of course, my model has no attribute 'items' since that is only the specification of the "plasmids" array. I have checked all my schemata against the Draft4Validator and they're fine. Am I using it in the wrong way within flask-restplus?

with open_text(sanger_service.schemata, "plasmid.json", encoding="utf-8") as file_handle: plasmid = api.schema_model('Plasmid', json.load(file_handle)) with open_text(sanger_service.schemata, "plasmids.json", encoding="utf-8") as file_handle: plasmids = api.schema_model('Plasmids', json.load(file_handle)) @api.marshal_with(plasmids)...

I'm using Python 3.6 and flask-restplus 0.10.1.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/noirbizarre/flask-restplus/issues/414, or mute the thread https://github.com/notifications/unsubscribe-auth/AHPX_Yni_NjszNekQfJ4h6eyYk1lox_yks5ti2ffgaJpZM4S-Z_U .

Midnighter commented 6 years ago

Possibly, but I have two more kinds of objects nested in arrays. So I don't know how I would do that for those.

nvgoldin commented 6 years ago

@Midnighter - hitting the same issue, did you get it working eventually?

Midnighter commented 6 years ago

I'm afraid I chose to directly build a dictionary structure instead of going for a class-based approach. So I didn't look into it further.

If I were to try again, I'd give marshmallow a shot.

j5awry commented 5 years ago

I just confirmed this bug. We're using a centralized jsonschema for a system -- lots of services, all take the same input. This is failing for us as well. short term, i'm going to figure out a workaround that's and then figure out the proper fix.

j5awry commented 5 years ago

Short term, you can remove the nesting with a separate package:

https://jsonref.readthedocs.io/en/latest/

Just tested for anchored local refs, and it worked great. Example from a file:

import jsonref

with open("myschema.json", "r") as fopen:
     j = jsonref.load(fopen)

If you're already in dict form, dump it then load it (just to make sure it's formatted properly)

j5awry commented 5 years ago

also see #275 . I'm investigating a stale PR to see if it'll work as a better fix.