hotmeteor / spectator

OpenAPI testing for PHP
MIT License
285 stars 53 forks source link

Validation on nested object with `allOf` does not work correctly #132

Closed Peac36 closed 9 months ago

Peac36 commented 2 years ago

I have the following case:

get:
  tags:
    - test
  summary: test
  description: test
  responses:
    '200':
      description: Success
      content:
        application/json:
          schema:
            type: object
            properties:
              data:
                type: array
                items:
                  allOf:
                    - type: object
                      properties:
                        id:
                          type: integer
                        NestedObject:
                          nullable: true
                          $ref: "NestedObject.yaml"
                    - $ref: "AnotherObject.yaml"
                    - $ref: "AnotherObject.yaml"

Validation error:

 NestedObject: object++ <== The data (null) must match the type: object

it seems the allOf ignores the nullable tag and required all properties to not be null. The same code without allOf(manually merging objects) seems to work fine.

According to swagger's documentation if all objects in allOf are valid then the merged object is valid as well, but here this does not seem to be true.

tsterker commented 2 years ago

@Peac36 In your case I assume the issue is that you declare nullable as a sibling element of $ref, which will be ignored, as per OpenAPI spec:

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

Any sibling elements of a $ref are ignored. This is because $ref works by replacing itself and everything on its level with the definition it is pointing at

I have not tested it, but I think you can fix this by using allOf in your NestedObject declaration:

Before:

NestedObject:
  nullable: true
  $ref: "NestedObject.yaml"

After:

NestedObject:
  allOf:
    - nullable: true
    - $ref: "NestedObject.yaml"
BobbyBorisov commented 1 year ago

@tsterker I tried to use your advice with allOf and validation still fails unfortunately. After that I used oneOf and it worked.

What do you think might be the issue with allOf?

When I generate html doc via redoc when I use oneOf it shows (any or null) or object but before it was just null or object. If I use allOf docs generated is as well null or object. I would be perfect if its working with allOf.

Cheers!

tsterker commented 1 year ago

@BobbyBorisov Sorry for misleading you. It actually also doesn't work for me either when using allOf.

I suspect this is related to these issues:

@jarrodparkes did an initial assessment on this, but it does not look like it was followed up on.

I'd love to delve deeper myself once I find some spare time. Maybe @hotmeteor could also have a look at it?

ronaldwanink commented 1 year ago

This keeps popping up here also once a while.. no clue how I get rid of it. But now again I have a simple situation:

vendor: string? <== The data (null) must match the type: string

so without $ref or AllOf(), will try to figure out what happens.

Update: an explicit conversion to (string) in the resource solves the issue. Adding the attribute to $casts does not solve it.