Swagger 2.0 to OpenAPI 3.1

Convert a Swagger 2.0 spec into OpenAPI 3.1.

Swagger 2.0 Input
OpenAPI 3.1 (YAML) Output
OpenAPI 3.1 spec appears here

Related Tools

Documentation

What is Swagger 2.0 to OpenAPI 3.1?

This tool converts a Swagger 2.0 API specification into OpenAPI 3.1 — the two are different enough structurally (not just a version bump) that a real conversion has to rewrite body/formData parameters into requestBody, move response schemas under content, and restructure security definitions, on top of the JSON-Schema-alignment changes that 3.1 specifically introduced over 3.0.

How it works

host, basePath, and schemes combine into a single servers entry. Every $ref pointing at #/definitions/... is rewritten to #/components/schemas/..., and the top-level definitions object becomes components.schemas directly. For each operation, a parameter with in: "body" becomes a requestBody whose content type comes from the operation's (or document's) consumes list; in: "formData" parameters are collected into one object schema instead, since OpenAPI has no per-field form parameter concept. Every other parameter's inline type/format/items fields move under a nested schema object, which is where OpenAPI expects them. Response schema fields move under content, keyed by the operation's produces list. securityDefinitions becomes components.securitySchemes, with oauth2's flat flow/authorizationUrl/scopes fields restructured into 3.1's nested flows object.

Features

  • host/basePath/schemes → a single servers URL
  • body/formData parameters → requestBody
  • Response schemacontent, keyed by produces
  • definitionscomponents.schemas, every $ref rewritten to match
  • oauth2 flow restructuring and boolean-exclusiveMinimum/Maximum → 3.1's numeric form, both flagged in an on-page warning banner
  • Output as either YAML or JSON

Example

Input (abridged):

{
  "swagger": "2.0",
  "host": "api.example.com",
  "basePath": "/v1",
  "schemes": ["https"],
  "paths": {
    "/users/{id}": {
      "get": {
        "parameters": [{ "name": "id", "in": "path", "required": true, "type": "string" }],
        "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/User" } } }
      }
    }
  },
  "definitions": { "User": { "type": "object", "properties": { "id": { "type": "string" } } } }
}

Output (abridged, JSON):

{
  "openapi": "3.1.0",
  "servers": [{ "url": "https://api.example.com/v1" }],
  "paths": {
    "/users/{id}": {
      "get": {
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } } }
      }
    }
  },
  "components": { "schemas": { "User": { "type": "object", "properties": { "id": { "type": "string" } } } } }
}

Common errors

A document missing the top-level "swagger": "2.0" field is rejected outright rather than guessed at — this tool only accepts genuine Swagger 2.0 input, not an OpenAPI 3.0 document that happens to be structurally similar. Vendor extensions (any x-* field) at the root or on individual operations are passed through only where this converter explicitly copies that section (info, tags, paths); a vendor extension nested somewhere this converter doesn't walk won't appear in the output, since guessing where to place an unrecognized extension risks putting it somewhere that changes its meaning.

Best practices

Read the warning banner above the output before treating the conversion as final — every best-effort substitution (the file type mapping, the exclusiveMinimum/Maximum numeric conversion) is listed there, not buried in the spec itself. Validate the result with a real OpenAPI 3.1 linter or an editor like Redocly before publishing it, since a structurally valid-looking spec can still have semantic gaps a linter catches that this converter's rule-based transform can't.

Frequently Asked Questions

Why 3.1 specifically, and not 3.0?

OpenAPI 3.1 aligns its schema keywords fully with JSON Schema 2020-12, which changes a couple of things Swagger 2.0 (and OpenAPI 3.0) express differently — most notably exclusiveMinimum/exclusiveMaximum, which are booleans paired with minimum/maximum in Swagger 2.0 but numeric bounds on their own in 3.1. This tool applies that specific 3.1 keyword change, not just the Swagger-to-3.0 structural transform other tools stop at.

How are body and formData parameters handled?

Swagger 2.0's "in: body" parameter becomes a requestBody with the same schema, keyed by whatever content types the operation (or the document) declares in "consumes". "in: formData" parameters are collected into a single object schema and wrapped in multipart/form-data or application/x-www-form-urlencoded, based on whether any of them use the "file" type.

What happens to Swagger's "file" type?

It becomes { type: "string", format: "binary" } — the standard, widely-used mapping, since OpenAPI has no dedicated file type of its own. This substitution is listed in the output's warning banner so it's never silently invisible.

Does it handle oauth2 security definitions?

Yes — Swagger 2.0's flat oauth2 definition (a single "flow" field plus authorizationUrl/tokenUrl/scopes) is restructured into OpenAPI 3.1's nested flows object, with Swagger's flow names remapped to their 3.1 equivalents (accessCode becomes authorizationCode, application becomes clientCredentials).