How to break swagger 2.0 JSON file into multiple modules
Asked Answered
J

7

37

I'm trying to break my API document up into multiple JSON files that can be edited independently. All the examples I've been able to find use the Swagger 1.2 schema which has a "api":{} object for breaking it down. That appears to be missing from the 2.0 schema (http://json.schemastore.org/swagger-2.0). All that defines is a single "paths" array where it bundles all the API endpoints into that single array. The effect of this in the swagger-ui is there is a single "default" category that everything gets bundled into and no way that I can tell to split it up.

TLDR: How do you split operations from paths in the swagger 2.0 schema

{
  "swagger": "2.0",
  "info": {
    "description": "My API",
    "version": "1.0.0",
    "title": "My API",
    "termsOfService": "http://www.domain.com",
    "contact": {
      "name": "[email protected]"
    }
  },
  "basePath": "/",
  "schemes": [
    "http"
  ],
  "paths": {
    "Authorization/LoginAPI": {
      "post": {
        "summary": "Authenticates you to the system and produces a session token that will be used for future calls",
        "description": "",
        "operationId": "LoginAPI",
        "consumes": [
          "application/x-www-form-urlencoded"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [{
          "in": "formData",
          "name": "UserName",
          "description": "Login Username",
          "required": true,
          "type": "string"

        }, {
          "in": "formData",
          "name": "Password",
          "description": "Password",
          "required": true,
          "type": "string"

        }],
        "responses": {
          "200": {
            "description": "API Response with session ID if login is allowed",
            "schema": {
              "$ref": "#/definitions/Authorization"
            }
          }
        }
      }
    }
  }
}
Joey answered 13/11, 2014 at 19:50 Comment(0)
M
28

You actually ask several questions in one, and I'll try answering them all.

In Swagger 1.2 and prior to it, the file splitting was mandatory and artificial. It was meant as a way to group operations, and Swagger 2.0 offers and alternative method to do that (more on it soon).

Swagger 2.0 is indeed a single file, which allows for external files wherever $ref is used. You cannot split a single service into several files and combine them as one, but you can specify operations for specific paths externally (again, using the $ref property).

We're currently in the process of finalizing the ability to collate several micro-services into a single collection, but eventually, each micro-service is still going to be a single file.

As mentioned, the grouping of operations in Swagger 2.0 has changed, and the concept of a 'resource' no longer exists. Instead, there are tags (with the "tags" property) which can be assigned per operation. The tags is an array of values, and unlike previous versions, each operation can exist under multiple tags if needed. In Swagger-UI, all operations that have no tags defined will end up under the default tag, which is the behavior you've seen. There's an additional tags property at the top-level object that allows you to add descriptions to tags and set their order, but it is not mandatory to include it.

As a final note, I have no idea how the json-schema of Swagger 2.0 ended up in http://json.schemastore.org/swagger-2.0 but it is certainly not up to date. The most up-to-date schema can be found here - http://swagger.io/v2/schema.json - and it is still under development. Keep in mind that the source of truth is the spec (https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md) and not the schema, so in case of conflicts, the spec 'wins'.

Edit:

We just published a guide on referencing. It may help with some use cases - https://github.com/OAI/OpenAPI-Specification/blob/master/guidelines/v2.0/REUSE.md

Miele answered 13/11, 2014 at 20:20 Comment(10)
So if I wanted to have separate files for each tag, is that possible? I can see putting all the resources (for example) into a separate file using the $ref, but how would you split up the "paths" array?Joey
You can't do that. Again, the micro-services solutions will come soon, but that doesn't necessarily mean that tag==micro-service.Miele
can you define paths and models in different files? Example of that in swagger 2.0?Saltsman
For models, you can $ref an external definition. For paths, there's a solution at the moment, but it has issues so it's better not to use it right now.Miele
Is there a solution yet? I am being forced to use Swagger 1.2 format because of it's simplicity to break giant api set into multiple files. I also need the ability to have each resource description in a separate file.Ellsworthellwood
Unfortunately, not yet.Miele
Hi Ron, I am using Swagger Core Jersey 1.X and it produces swagger 1.2 spec while many other tools use swagger 2.0 spec. Is there a proper way to generate 2.0 spec?Pupa
Follow github.com/swagger-api/swagger-core/wiki/… and github.com/swagger-api/swagger-core/wiki/1.3--1.5-Migration.Miele
hi Ron, is there a solution to the "collate several micro-services into a single collection", I am not able to find any references in the above links!Mozarab
There isn't a full solution, no. It'll probably get addressed in the next version of the spec.Miele
M
10

I've written about this in this blog post. You can basically use JSON Refs library to resolve all your little Swagger files into one large one and use it in the tools.

Monogenesis answered 26/7, 2015 at 20:32 Comment(2)
Some (most?) examples in the blog post are wrong. $ref is not allowed everywhere, it's only allowed in limited places - where the Specification explicitly states the value of a keyword can be a "Reference Object". For instance, info: {$ref: ./info/index.yaml} is NOT valid, and so are some other examples.Nominate
@Nominate My tool openapi-preprocessor is what you need.Arlberg
G
3

If JSON ref's didn't work for you, it might be useful to write your own concatenator. Well, instead of writing your own you can actually use something that is already out there. Any templating engine will do. In my case Handlebars turned out to be very helpful (because Handlebars actually preserves indentation, which is perfect for Yaml files since they are case sensitive).

Then you can have a build script in Node:

'use strict';

var hbs = require('handlebars');
var fs  = require('fs');

var dir = __dirname + '/your_api_dir';

var files = fs.readdirSync(dir);

files.forEach((fileName) => {
  var raw = fs.readFileSync(dir + '/' + fileName, 'utf8');
  hbs.registerPartial(file, raw);
});

var index = fs.readFileSync(dir + '/index.yaml');

var out = hbs.compile(index.toString());

Read more regarding the issue on my blog.

Grandniece answered 18/2, 2016 at 17:53 Comment(2)
Why minus to this reply? JSON refs are mentioned and everything else is a viable workaround (I do not like it much though, but for some use cases it could prove to be the easiest approach).Publius
Blog link is dead, and Oleg hasn't been on in a while. Here's a link to a snapshot of the blog page from Wayback Machine: web.archive.org/web/20160209064025/http://olegberman.com/…Confetti
C
2

Note that RepreZen API Studio now supports multi-file Swagger/Open API projects via the $ref syntax discussed here. So you can break up large Swagger projects into modules to enable re-use and team collaboration. You can then use the built-in Swagger normalizer to create a single, consolidated Swagger file when you need to take your API model outiside the design/development environment.

Note: in the interests of full disclosure, I am Product Manager at RepreZen. I stumbled across this thread last week and thought I'd chip in.

Circinate answered 30/9, 2016 at 10:45 Comment(0)
K
1

I'm trying to figure this out as well, and there's some useful info in the Swagger Google group. It looks like the consensus is that you can break the definitions out into separate files as long as the $ref is pointing to an absolute url. Example here:

https://github.com/swagger-api/swagger-spec/blob/master/fixtures/v2.0/json/resources/resourceWithLinkedDefinitions.json#L32

https://github.com/swagger-api/swagger-spec/blob/master/fixtures/v2.0/json/resources/resourceWithLinkedDefinitions_part1.json

Kinnard answered 3/4, 2015 at 4:4 Comment(0)
M
0

If json does not work for you bis, you can also and you use node.js, you can also use module.exports

I have my definitions in modules, and I can require a module within a module:

const params = require(./parameters);
module.exports = {
  description: 'Articles',
  find: {
    description: 'Some description of the method', 
    summary: 'Some summary',
    parameters: [
        params.id,
        params.limit,


...
Mayday answered 22/3, 2017 at 8:10 Comment(0)
D
0

Swagger JSON can be split in multiple modules by creating docket for each module like this:

`

@Bean
public Docket module1() {
      return new Docket(DocumentationType.SWAGGER_2)
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.example.module1"))
        .paths(PathSelectors.any())
        .build()
        .groupName("module1")
        .apiInfo(apiInfo());
}

`

For each module URL will be created like http://localhost:xxxx/context-path/v2/api-docs?group=module1

Dave answered 14/5, 2020 at 8:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.