34

I'd like to convert a Swagger YAML file to JSON from the command line. The plan is to use this command line during a CI job. I've searched on google and found many solutions, but most of them use Python or Ruby, which I'd prefer not to use. For example: http://www.commandlinefu.com/commands/view/12218/convert-yaml-to-json

I'd like to do this without using Python or Ruby, and I'd also like to be able to control the leading whitespace when formatting the JSON to match exactly the JSON that is output from Swagger's editor.swagger.io editor, when you choose File -> Download JSON

All this means is that I'd like the whitespace padding to be four spaces, like so:

{
    "swagger": "2.0",
    "info": {
        "title": "API TITLE",

I haven't tried the Python method in the link above, but the Ruby method uses two space whitespace padding. Perhaps there is a way to control that, but I don't want to use Ruby or Python in this solution anyway.

I'm sure that there are many "correct" answers to this question. I am looking for the solution that is most elegant with the least number of dependencies. Ideally, a diff of the resulting JSON file against a JSON file generated by the editor.swagger.io should be empty.

mkrufky
  • 3,268
  • 2
  • 17
  • 37

8 Answers8

27

I think that you are looking for the swagger-codegen (now OpenApi-generator) functionality:

Running

swagger-codegen generate -i swagger.yaml -l swagger

will out put a swagger.json in the same location.

Update For CI: If you can install it on your build machine- good for you. If you can't - the github page has a link to a docker image with a nodejs server is available (to convert using a curl command as suggested in a different answer).

Update For Docker: If you use Docker, try swaggerapi/swagger-codegen-cli, there is an example for docker-compose that might help a few answers down by Fabian & ckeeney.

Update about OpenApi:

This question is about swagger, and a few years old. If you're just starting to use Swagger you should switch to OpenApi instead, and if you have existing swagger files, i suggest migrating.

Liel
  • 474
  • 4
  • 8
  • 1
    I *do* like this answer, but a docker image is quite a heavy dependency. There should be a way to send the YAML spec to the POST endpoint that `generator.swagger.io` points to, which itself uses `swagger-codegen` but I can't figure out how to send a spec in the POST body :-/ – mkrufky Jan 13 '16 at 21:09
  • 1
    I just did an *npm install -g swagger-codegen* and it did not include that command! When I installed *npm install -g swagger-codegen-cli* the swagger-codegen-cli was available. – PatS Aug 29 '18 at 22:22
  • The install scripts fail currently, because `central.maven.org` is not accessible using wget or curl. I was only able to download the jar files from a browser. BTW the Java dependency is a big con. It's awful that there's no plain php/nodejs tool that supports version 3. – Crouching Kitten Aug 20 '19 at 11:01
  • 1
    When I tried using swagger codegen, the `swagger` output format was not supported by the version I got from brew. – Robert P. Goldman May 01 '20 at 20:03
  • @RobertP.Goldman probably because brew is downloading the latest version (3.+), which doesn't support 'swagger' as language, but 'openapi' or 'openapi-yaml'. To be able to use swagger, you need to use version 2. – user3037726 Jul 07 '20 at 17:28
  • With version 3 of swagger-codegen here is the command you can run to convert a YAML swagger file to JSON: `swagger-codegen generate -i swagger.yaml -l openapi -o output_dir`. Then your file will be in `output_dir/openapi.json`. To do JSON -> YAML just specify a JSON file instead of Swagger and change 'openapi' to 'openapi-yaml'. – Luke Mat Jul 25 '20 at 01:23
  • 2
    I found that `openapi-generator` supported the OpenAPI specs I had. `swagger-codegen` is older, and also seems to have some bugs. I believe `openapi-generator` should always be preferred these days. @Liel Maybe update your answer? – Robert P. Goldman Jan 09 '21 at 16:33
  • @RobertP.Goldman updated it in hope the next visitors won't waste time on the outdated swagger tool. – Liel Mar 05 '21 at 14:20
10

swagger-codegen cli interface

As Liel has already pointed out, you can run

swagger-codegen generate -i swagger.yaml -l swagger

Docker

If you use Docker, then I suggest you try swaggerapi/swagger-codegen-cli.

You can generate a json file using docker with the following command:

docker run -v ./docs:/docs swaggerapi/swagger-codegen-cli generate -i /docs/swagger.yaml -l swagger -o /docs

I like to setup a docker-compose.yml to "alias" this command for easy reuse:

version: "2"
services:
  gen-swagger:
    volumes:
      - ./docs:/docs
    image: swaggerapi/swagger-codegen-cli
    command: generate -i /docs/swagger.yaml -l swagger -o /docs

And now I can just run docker-compose run gen-swagger

Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
ckeeney
  • 1,270
  • 13
  • 18
10

Another possibility to convert a swagger.yml file to swagger.json is a NPM package called swagger-cli.

npm install -g swagger-cli

Then you can convert a yml to json file:

swagger-cli bundle -o api-spec.json api-spec.yml
Sebastian
  • 868
  • 9
  • 13
  • 1
    Good answer, except that the question asks for minimum dependencies. If you are are already a Node user, this is great. Otherwise, not so much. But there must be a way to use `swagger-cli` from a Docker image. – Robert P. Goldman Jan 09 '21 at 16:36
  • Looks like there's a docker image for this now: https://hub.docker.com/r/jeanberu/swagger-cli `docker run --rm -v $PWD/pkg/libv1/api/openapi:/openapi jeanberu/swagger-cli swagger-cli bundle -o /openapi/common.json /openapi/common.yaml` – chaseisabelle Jun 24 '22 at 19:43
9

Using yamljs:

yaml2json swagger.yaml -p -i4

The output from this command diff'd against the JSON output from editor.swagger.io produces an empty diff.

This is indeed what I'm looking for, but it brings in a huge dependency (node). I'm hoping for something even lighter, yet equally as elegant as this.

mkrufky
  • 3,268
  • 2
  • 17
  • 37
  • 4
    There is a serious "con" with that way: cross-file relations are not translated. Example: `$ref: 'Pet.yaml'` should be translated to `$ref: 'Pet.json'` – Rémi Becheras Jul 18 '16 at 15:15
9

For version swagger-codegen 3.0.4

Use

swagger-codegen generate -i my_yaml.yaml -l openapi

to get a .json.

kuzdu
  • 7,124
  • 1
  • 51
  • 69
6

You can use the online swagger codegen project to do this:

curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" -d "{
  \"spec\": {}
}" "https://generator.swagger.io/api/gen/clients/swagger-yaml"

Put the value of your swagger definition in the spec object. You'll get a link to download the converted & validated spec, in yaml format.

For options, take a look here:

http://generator.swagger.io/

fehguy
  • 6,724
  • 25
  • 23
  • 1
    This is exactly the kind of answer I'm looking for, but reverse: I want to convert from YAML to JSON. I'd assume that instead I'd want to use `https://generator.swagger.io/api/gen/clients/swagger` and perhaps use the mimetime `application/x-yaml` ? For argument's sake I tried using a JSON file and converting to yaml but both your command line and the api-explorer on `http://generator.swagger.io` don't seem to like the `spec` field. Any exact command line example for how to use the `spec` field in the POST body? I'd suggest adding `default` value for this endpoint illustrating this... – mkrufky Jan 12 '16 at 21:32
  • 3
    The generator doesn't support that right now but it can. I've opened this issue, which you can track for progress: https://github.com/swagger-api/swagger-codegen/issues/1903 – fehguy Jan 15 '16 at 18:31
2

I'd use https://openapi-generator.tech/

It's an npm install (I just used it locally npm install @openapitools/openapi-generator-cli) and then

npx @openapitools/openapi-generator-cli generate -i source.yaml -g openapi -o outputdir
0llie
  • 8,758
  • 2
  • 24
  • 13
0

For a gradle with Kotlin, i've wrote in my build.gradle.kts:

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import java.nio.file.Path

and then in a some task like compileJavacode for convertation:

val compileJava: Task by tasks.getting {
  val openApiDir = "${rootProject.projectDir}/openapi"    
  val json: JsonNode? = ObjectMapper(YAMLFactory())
    .readTree(Path.of("$openApiDir/openapi.yaml").toFile())
  ObjectMapper().writerWithDefaultPrettyPrinter()
    .writeValue(Path.of("$openApiDir/openapi.json").toFile(), json)
}
Nashev
  • 490
  • 4
  • 10