Split OpenApi Paths into multiple path definition files
Asked Answered
W

1

8

I want to split my paths (which are quite many) more easily into their own files.

Let's say I've got two major paths /user and /anotherPath with several subpaths. Now I've got an OpenApi spec file, whose paths are being referenced to an index file which holds references to each paths. Defining EVERY path with its' reference works, but is clumsy to write.

I want something like this:

openapi.json

{
...
  "paths": {
    "$ref": "paths/index.json"
  }
...
}

paths/index.json

{
  "/user": { // and everything that comes after user, e.g. /user/{userId}
    "$ref": "./user-path.json"
  },
  "/anotherPath": {  // and everything that comes after anotherPath, e.g. /anotherPath/{id}
    "$ref": "./anotherPath-path.json"
  }
}

paths/user-path.json

{
  "/user": {
    "get": {...}
  },
  "/user/{userId}": {
    "get": {...}
  }
}

paths/anotherPath-path.json

{
  "/anotherPath": {
    "get": {...}
  },
  "/anotherPath/{id}": {
    "get": {...}
  }
}

This way, whenever I add another path to /user or /anotherPath, I can simply edit their respective path file, e.g. paths/user-path.json.

EDIT1: Apparently, this topic is being discussed already.. For anyone interested: https://github.com/OAI/OpenAPI-Specification/issues/417 . By the way, I know that a $ref is not valid for the paths Object, but once figuring out how to properly split, this may not be necessary anymore.

Whipsaw answered 21/4, 2020 at 10:4 Comment(1)
O
13

OpenAPI does not have a concept of sub-paths / nested paths, each path is an individual entity. The paths keyword itself does not support $ref, only individual paths can be referenced.

Given your user-path.json and anotherPath-path.json files, the correct way to reference path definitions is as follows:

{
  ...
  "paths": {
    "/user": {
      "$ref": "paths/user-path.json#/~1user"  // ~1user is /user escaped according to JSON Pointer and JSON Reference rules
    },
    "/user/{id}": {
      "$ref": "paths/user-path.json#/~1user~1%7Bid%7D"  // ~1user~1%7Bid%7D is /user/{id} escaped 
    },
    "/anotherPath": {
      "$ref": "paths/anotherPath-path.json#/~1anotherPath"  // ~1anotherPath is /anotherPath escaped
    },
    "/anotherPath/{id}": {
      "$ref": "paths/anotherPath-path.json#/~1anotherPath~1%7Bid%7D"  // ~1anotherPath~1%7Bid%7D is /anotherPath/{id} escaped
    }
  }
  ...
}

YAML version:

paths:
  /user:
    $ref: "paths/user-path.json#/~1user"
  /user/{id}:
    $ref: "paths/user-path.json#/~1user~1%7Bid%7D"
  /anotherPath:
    $ref: "paths/anotherPath-path.json#/~1anotherPath"
  /anotherPath/{id}:
    $ref: "paths/anotherPath-path.json#/~1anotherPath~1%7Bid%7D"


If you want to use $ref in arbitrary places (other than where OAS allows $refs), you'll have to pre-process your definition using a parser/tool that can resolve arbitrary $refs; this will give you a valid OpenAPI file that can be used with OpenAPI-compliant tools. One such pre-processing tool is json-refs, you can find an example of pre-processing here.

Outmoded answered 21/4, 2020 at 12:32 Comment(3)
This is my current setup, but I find it redundant to write the exact path 2 times: 1 in paths and 1 in user-path.json. Guess I will have to wait for paths to accept something like patternpropertiesWhipsaw
Alternatively, you can use your example with $ref directly under paths, but use a JSON $ref resolver (not OpenAPI resolver) to bundle everything into a single file - see the updated answer.Outmoded
Actually, e.g. the Swagger Previewer renders $ref directly in paths pretty well. I'm using a VS Code + Swagger Previewer extension and that works well. Only splitting of Path Item Objects for easier usage with many (sub)routes is not supproted. I will look into manually pre-processing, thanks.Whipsaw

© 2022 - 2024 — McMap. All rights reserved.