Skip to content

can't get to validate GeoJSON features using openapi-core, oneOf and enum #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
michalmiesiak opened this issue Nov 7, 2018 · 4 comments
Labels
area/schema Indicates an issue on schema area kind/enhancement

Comments

@michalmiesiak
Copy link

michalmiesiak commented Nov 7, 2018

Hello,
I'm trying to integrate openapi-core with the test suite of my Flask API, so that all requests that I test are verified against the specification. Before I used the flex.core lib and Swagger 2.0 specification, but now I must pass on to OpenApi 3.0 (not supported by flex), so I chose openapi-core (my current version: 0.7.1). I use the FlaskOpenAPIRequest wrapper class on the flask.request object, within the correct context etc.

My problem is that I can't validate any HTTP requests that contain GeoJSON geometries in their bodies. The library "thinks" that more than one schema satisfies the specification whereas it is not the case. Thus, the validation always fails. The error I get is:

InvalidMediaTypeValue: Mimetype invalid: Invalid schema property areas: Invalid schema property geometry: Exactly one schema type SchemaType.OBJECT should be valid, more than one found

I think this might be due to a bug with oneOf choosing from schemas that contain enum, but maybe I'm doing something wrong?

Below details on requests that I make.

So, my request has a JSON body:

      tags:
        - [...]
      parameters:
        - [...]
      responses:
        [...]
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewLayer
        required: true

NewLayer are basically lists of geojson geometries with some additional properties, like in an example test body that I send:

{
        "name": "Places in Bordeaux",
        "areas": [
            {
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [
                        [
                            [
                                -0.5781233310699463,
                                44.84706857978168
                            ],
                            [
                                -0.576556921005249,
                                44.84687080641056
                            ],
                            [
                                -0.5747973918914795,
                                44.84725874584433
                            ],
                            [
                                -0.5743038654327393,
                                44.8486203165129
                            ],
                            [
                                -0.5761599540710449,
                                44.84973084752832
                            ],
                            [
                                -0.579303503036499,
                                44.849137552800435
                            ],
                            [
                                -0.5795502662658691,
                                44.84646765089727
                            ],
                            [
                                -0.5781233310699463,
                                44.84706857978168
                            ]
                        ]
                    ]
                },
                "area_id": "bdx_place_1",
                "name": "test-area"
            }
        ]
    }

To resume briefly the problem, each geometry element in my OpenApi specification has a choice of one of 5 schemas.

    Geometry:
      type: object
      oneOf:
        - $ref: '#/components/schemas/Point'
        - $ref: '#/components/schemas/LineString'
        - $ref: '#/components/schemas/MultiLineString'
        - $ref: '#/components/schemas/Polygon'
        - $ref: '#/components/schemas/MultiPolygon'

The elements that "conflict" are MultiLineString and Polygon (if I remove any of these, all works!).
Yet, they are different because they have a type field that is an enum with only one allowed value! So both can never be valid both at a time.
On the other hand, their coordinates fields can be both valid a time. That's what makes me think that enum fields are not handled correctly by the .

Below the definitions:

    MultiLineString:
      type: object
      required:
        - type
        - coordinates
      properties:
        type:
          description: Geometry type
          type: string
          enum:
            - MultiLineString
        coordinates:
          type: array
          items:
            type: array
            items:
              $ref: '#/components/schemas/Point2D'
            minItems: 2

    Polygon:
      type: object
      required:
        - type
        - coordinates
      properties:
        type:
          description: Geometry type
          type: string
          enum:
            - Polygon
        coordinates:
          type: array
          items:
            type: array
            items:
              $ref: '#/components/schemas/Point2D'
            minItems: 3

    Point2D:
      type: array
      maxItems: 2
      minItems: 2
      items:
        type: number

I will be very glad for any help! :-)
Thank you.

@michalmiesiak
Copy link
Author

michalmiesiak commented Nov 10, 2018

Hello,
just to let you know that I've found a workaround. If I merge both definitions (Polygon and MultiLineString), all works.
The new spec looks like this:

    PolygonOrMultiLineString:
      type: object
      description: GeoJson polygon or multi line string (both have same coordinates schema, only types differ)
      externalDocs:
        url: 'http://geojson.org/geojson-spec.html#id4'
      required:
        - type
        - coordinates
      properties:
        type:
          description: Geometry type
          type: string
          enum:
            - Polygon
            - MultiLineString
        coordinates:
          type: array
          items:
            type: array
            items:
              $ref: '#/components/schemas/Point2D'
            minItems: 2
    Geometry:
      type: object
      description: "GeoJson geometry: accepted elements are: `Point`, `LineString`, `MultiLineString`, `Polygon` and `MultiPolygon`"
      externalDocs:
        url: 'http://geojson.org/geojson-spec.html#geometry-objects'
      oneOf:
        - $ref: '#/components/schemas/Point'
        - $ref: '#/components/schemas/LineString'
#       - $ref: '#/components/schemas/MultiLineString'
#       - $ref: '#/components/schemas/Polygon'
# merged both because of specification validation issues (same coordinates scheme)
        - $ref: '#/components/schemas/PolygonOrMultiLineString'
        - $ref: '#/components/schemas/MultiPolygon'

This might look strange to a customer reading the spec, but I'm gonna stick to that for the moment. Yet I publish this because I hope it can help you!
Thanks,
Michal

@p1c2u
Copy link
Collaborator

p1c2u commented Nov 15, 2018

@michalmiesiak thanks for the report. The only difference between Polygon and MultilineString is minItems which is currently not supported that's why it finds two valid schemas and makes whole schema invalid (OneOf defines it should be exactly one).

@p1c2u p1c2u added kind/enhancement area/schema Indicates an issue on schema area labels Nov 15, 2018
@gigimon
Copy link

gigimon commented Sep 4, 2019

@p1c2u any news about this feature?

@p1c2u
Copy link
Collaborator

p1c2u commented Sep 4, 2019

@gigimon I'm in process of rewriting schema validation part that should fix most of issues related to this area including minItems

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/schema Indicates an issue on schema area kind/enhancement
Projects
None yet
Development

No branches or pull requests

3 participants