pb33f / libopenapi

libopenapi is a fully featured, high performance OpenAPI 3.1, 3.0 and Swagger parser, library, validator and toolkit for golang applications.
https://pb33f.io/libopenapi/
Other
482 stars 64 forks source link

Merging with anchors is not functioning as expected #325

Closed Jakousa closed 2 months ago

Jakousa commented 3 months ago

Aliases / anchors do not behave correctly with libopenapi. Anchors replace the object completely, instead of merge as expected:

Example code:

package main

import (
    "fmt"
    "os"

    "github.com/pb33f/libopenapi"
)

func main() {
    file, _ := os.ReadFile("./test.yaml")
    document, _ := libopenapi.NewDocument(file)
    docModel, _ := document.BuildV3Model()

    fmt.Println("Start")
    for pathPairs := docModel.Model.Paths.PathItems.First(); pathPairs != nil; pathPairs = pathPairs.Next() {
        pathItem := pathPairs.Value()
        for methodPairs := pathItem.GetOperations().First(); methodPairs != nil; methodPairs = methodPairs.Next() {
            methodValue := methodPairs.Value()

            fmt.Println("Responses: ", methodValue.Responses)
        }
    }
    fmt.Println("End")
}

Example yaml:

openapi: 3.0.0

x-anchors:
  operation: &operation
    summary: Test
    operationId: test

info:
  title: Title
  version: 1.0.0
  description: Description
  contact: Contact

servers:
  - url: https://url

paths:
  /test:
    get:
      <<: *operation
      responses:
        '200':
          description: Test
          content:
            application/json:
              schema:
                type: array

Output:

Start
length of responses:  <nil>
End

Expected something like:

Start
Responses:  &{0xc00005a288 <nil> 0xc00005a280 0xc0003040e0}
End

Leads to nil responses object, even though the operation should be merged with the responses.

petkostas commented 2 months ago

Might be related.

Edit: I did a quick check according to the response to this issue

openapi: 3.0.0

operation: &operation
  /test:
    get:
      summary: A get
      operationId: a-get
      responses:
        "200":
          description: Test

info:
  title: Title
  version: 1.0.0
  description: Description
  contact: Contact

servers:
  - url: https://url

paths:
  <<: *operation

Output (I changed the code to output the description):

│Start                                                                                                                                                                                                                             │
│2024/08/27 20:16:38 INFO Pathitem is pathItem="&{Tags:[] Summary:A get Description: ExternalDocs:<nil> OperationId:a-get Parameters:[] RequestBody:<nil> Responses:0x14000222540 Callbacks:<nil> Deprecated:<nil> Security:[] Serv│
│ers:[] Extensions:0x140000aa008 low:0x14000228008}"                                                                                                                                                                               │
│Responses:  Test                                                                                                                                                                                                                  │
│End  

I recommend avoiding using YAML anchors and embeds. The OAS provides the schema ability to use $ref for the same purpose.

daveshanley commented 2 months ago

Closing this as there is nothing I can do to fix it. But it's good to document known behavior.