python-openapi / openapi-core

Openapi-core is a Python library that adds client-side and server-side support for the OpenAPI v3.0 and OpenAPI v3.1 specification.
BSD 3-Clause "New" or "Revised" License
306 stars 132 forks source link

referencing a json-schema from openapi3 #90

Open sanderegg opened 6 years ago

sanderegg commented 6 years ago

Hello,

I am currently in the process of creating a python based REST api. I wrote an openapi 3.0 interface that reference an external json-schema file using $ref: 'test.json' (openapiref)[https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject] as I thought this is supposed to be possible.

Now I wanted to use openapi-core to validate requests and responses but I hit a problem which is that the validation of my openapi interface file does not go through because I get an error of type:

{'description': 'some external json', 'content': {'application/json': {'schema': {'$ref': './test.json', 'x-scope': ['file:///c:/Users/anderegg/Documents/dev/OSPARC/jsonschematest/testapi.yaml']}}}}
is not valid under any of the given schemas

Failed validating 'oneOf' in schema['properties']['paths']['patternProperties']['^/']['properties']['get']['properties']['responses']['properties']['default']:
    {'oneOf': [{'$ref': '#/definitions/response'},
               {'$ref': '#/definitions/reference'}]}

On instance['paths']['/']['get']['responses']['default']:
    {'content': {'application/json': {'schema': {'$ref': './test.json',
                                                 'x-scope': ['file:///c:/Users/anderegg/Documents/dev/OSPARC/jsonschematest/testapi.yaml']}}},
     'description': 'some external json'}

my example openapi interface looks like this:

# test.yaml
openapi: "3.0.0"
info:
  description: This is a test api
  version: 1.0.0
  title: Test API

paths:
  /:
    get:
      tags: 
        - users
      summary: Returns a nice greeting
      description: Returns a nice greeting
      operationId: root_get
      responses:
        default:
          description: some external json
          content:
            application/json:
              schema:
                $ref: './test.json'

and my example json-schema:

// test.json
{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Test",
    "type": ["string", "null"],
    "format": "date-time"
}

Now I understand the problem comes from factories.py:SpecFactory:create where openapi_spec_validator is failing in validating my file because the ref does not follow #/something.

Am I wrong in thinking I can direclty reference a JSON schema? If not, is it possible to disable the spec validation from client side? Or should I change something in the way I reference it?

Thanks for any input on this...

p1c2u commented 6 years ago

@sanderegg hi. It is possible to use external files. You need to pass additional parameter spec_url='file:///path/to/your/openapi.yaml' when creating spec.

Your test.json is not valid because there is no null type in OpenAPI 3. See nullable

sanderegg commented 6 years ago

Hi @p1c2u , Yes I did this, I actually realise I forgot to show the python code:

from openapi_spec_validator import validate_spec, factories
from openapi_core import create_spec
from openapi_core.shortcuts import RequestValidator
from pathlib import Path
import yaml
import json

SPEC_FILE = Path(__file__).parent / "testapi.yaml"
with SPEC_FILE.open() as fp:
    specification_dict = yaml.load(fp)
uri = SPEC_FILE.as_uri()

try:
    # factories.config
    spec = create_spec(specification_dict, spec_url=uri)
    validator = RequestValidator(spec)
except Exception as err:
    print(err)
p1c2u commented 6 years ago

The element of the document located on the same server should look like follow – $ref: 'test.json'

https://swagger.io/docs/specification/using-ref/#syntax

sanderegg commented 6 years ago

I tried $ref: 'test.json' and $ref: './test.json' both return the same error as explained above. The latter works better in some other packages. Actually the problem is not in finding the file, this works. The problem is I think that it is not looking like:

{'oneOf': [{'$ref': '#/definitions/response'},
               {'$ref': '#/definitions/reference'}]}
p1c2u commented 6 years ago

@sanderegg it works for me after fixing `null issue

f = open('testapi.yaml')
spec_dict = safe_load(f)
spec = create_spec(spec_dict, spec_url='file:///path/to/file/test.yaml')
sanderegg commented 6 years ago

@p1c2u what do you mean fixing `null issue?

p1c2u commented 6 years ago

@sanderegg see my first comment

sanderegg commented 6 years ago

so you changed to

// test.json
{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Test",
    "type": ["string"],
    "format": "date-time"
}

is that correct? cause for me I still get the very same error .

p1c2u commented 6 years ago

There is no such keyword as $schema and type should be string

Here is valid:

// test.json
{
    "title": "Test",
    "type": "string",
    "format": "date-time",
    "nullable": true
}
sanderegg commented 6 years ago

Ok, but then it is not anymore a json-schema but a openapi. So it is not possible to mix them together in that case.

p1c2u commented 6 years ago

Hmm. What can I say more. It's OpenAPI library and OpenAPI schema is subset of JSONSchema

The Schema Object allows the definition of input and output data types. This object is an extended subset of the JSON Schema Specification Wright Draft 00.

sanderegg commented 6 years ago

ok, so after hours of research it's actually possible folowing: this and this.

So, using a json-schema file, passing it through the json-schema-to-openapi converter and then in the openapi-validator. The node command line tool speccy actually validates an openapi with integrated json-schema inside using the -j flag.

p1c2u commented 6 years ago

Thanks for the info. It's a bit hacky. "More Proper Solution" looks good. Now we need to wait for OpenAPI 3.1 release.

HRogge commented 5 years ago

What is the status of this issue? The incompatibility with JSONSchema is a disaster, especially with more complicated Schemata (with internal or external references).

thierrydallacroce commented 5 years ago

ok, so after hours of research it's actually possible folowing: this and this.

The above links appeared to have been moved to this and this .