Swagger 2.0 to OpenAPI 3.1
Convert a Swagger 2.0 spec into OpenAPI 3.1.
Related Tools
Convert a Postman collection into an OpenAPI 3.0 spec.
Convert an OpenAPI 3.0 spec into a Postman collection.
Validate JSON against a JSON Schema with JSON-pointer error paths.
Convert a cURL command into a Python requests call.
Convert a cURL command into a Go net/http request.
Convert a cURL command into a Node.js fetch call.
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 singleserversURLbody/formDataparameters →requestBody- Response
schema→content, keyed byproduces definitions→components.schemas, every$refrewritten 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).