What changed structurally from Swagger 2.0 to OpenAPI 3.0 in a spec document?
answer
- One host key becomes an array
- Body parameters stop being parameters
- Media type now owns the schema
- Reuse buckets consolidate under one key
- Every $ref pointer path changes
basics
~20 sOpenAPI 3.0 replaced Swagger 2.0's host, basePath and schemes with a servers array, turned body and formData parameters into requestBody, replaced document-level consumes and produces with per-operation content maps, and moved definitions, parameters, responses and securityDefinitions under components.
solid answer
~40 sThe root key changes from `swagger: "2.0"` to `openapi: "3.0.x"`. Four structural moves matter. First, the single `host` + `basePath` + `schemes` triple becomes a `servers` array of full, optionally templated URLs, so one document can describe several environments. Second, the `in: body` and `in: formData` parameters disappear; payloads become a `requestBody` object whose `content` is keyed by media type, which also retires the document-level `consumes` and `produces`. Third, all reusable definitions consolidate under `components`: `definitions` becomes `components.schemas`, `securityDefinitions` becomes `components.securitySchemes`, and new buckets appear for `requestBodies`, `headers`, `examples`, `links` and `callbacks` — so every `$ref` path changes. Fourth, schemas gain `oneOf`, `anyOf` and `not` alongside `allOf`, cookie parameters become expressible, and `collectionFormat` gives way to `style` and `explode`.
code
yaml · 18 lines# Swagger 2.0
swagger: "2.0"
host: api.example.com
basePath: /v1
schemes: [https]
consumes: [application/json]
paths:
/orders:
post:
parameters:
- name: body
in: body
required: true
schema:
$ref: '#/definitions/NewOrder'
definitions:
NewOrder:
type: objectgo deeper
Recall that Swagger 2.0 and OpenAPI 3.x are the same lineage, and that 3.x uses servers, requestBody and components where 2.0 used host, body parameters and definitions.
Explain each structural move and why it was made — especially media-type-keyed content replacing the flat consumes/produces lists.
Show what a real migration costs: rewritten $ref pointers across tooling, reworked security schemes, and the fact that a converted document stays shaped like 2.0 until someone redesigns it.
Own the decision of whether to migrate at all — consumer impact, SDK regeneration, gateway support for 3.x, and whether the new expressiveness pays for the coordination.
## Why this question is asked Plenty of live systems still serve a Swagger 2.0 document, and plenty of engineers learned the format there. An interviewer wants to know you can read both, and that you understand a 2.0 → 3.0 conversion is a restructuring of the document rather than a version-number bump. ## The root `swagger: "2.0"` becomes `openapi: "3.0.3"` (or whichever 3.0.x patch). `info` survives essentially unchanged, still requiring `title` and `version`. ## Hosts: three flat keys become an array Swagger 2.0 described exactly one deployment: `host: api.example.com`, `basePath: /v1`, `schemes: [https]`. A document could therefore describe only one server, and multi-environment setups resorted to templating the file at build time. OpenAPI 3.0 replaces all three with `servers`, an array of Server Objects. Each holds a full `url`, which may be relative and may contain `{variable}` placeholders backed by a `variables` map (each variable requires a `default`, and may restrict values with `enum`). Prod, staging and regional hosts now live in one document, and `servers` can additionally be overridden on a path item or a single operation. ## Request payloads: body parameters become requestBody In 2.0, the payload was smuggled in as a parameter with `in: body` (at most one per operation, carrying a `schema`) or as several `in: formData` parameters for form submissions. The media types the operation accepted were listed separately in `consumes`, at document or operation level, with no link between a given media type and a given schema. OpenAPI 3.0 introduces a first-class `requestBody` object with its own `required` flag, `description`, and a `content` map keyed by media type — each key carrying its own `schema`, `example`/`examples` and `encoding`. Form submissions become `application/x-www-form-urlencoded` or `multipart/form-data` entries in that same map. This means one operation can genuinely accept a JSON body and a CSV body with different schemas, which 2.0 could not express. The mirror-image change applies to responses: `produces` disappears and each response gets a `content` map keyed by media type. ## Reuse: everything consolidates under components Swagger 2.0 scattered reusable objects across root-level keys: `definitions`, `parameters`, `responses`, `securityDefinitions`. OpenAPI 3.0 gathers them into a single `components` object with the buckets `schemas`, `responses`, `parameters`, `examples`, `requestBodies`, `headers`, `securitySchemes`, `links` and `callbacks`. The practical consequence is that every reference changes: `$ref: '#/definitions/Pet'` becomes `$ref: '#/components/schemas/Pet'`. Any hand-written tooling, documentation snippet or test fixture that hard-codes 2.0 pointer paths breaks on conversion. ## Security declarations `securityDefinitions` moves to `components.securitySchemes`, and the scheme shapes change. 2.0's `type: basic` becomes `type: http` with `scheme: basic`, which is also how bearer tokens are now expressed. OAuth2's single `flow` key with a sibling `authorizationUrl`/`tokenUrl` becomes a `flows` object that can declare several flows at once, each with its own URLs and scopes. The way requirements are *applied* — a root-level or operation-level `security` array — is unchanged in shape. ## Schemas and parameter serialization Swagger 2.0's schema subset supported only `allOf`. OpenAPI 3.0 adds `oneOf`, `anyOf` and `not`, plus `nullable`, `deprecated`, `writeOnly` and a richer `discriminator` object, which is what finally made polymorphic payloads describable. Parameter serialization also changed: 2.0's `collectionFormat` (`csv`, `ssv`, `pipes`, `multi`) is replaced by the `style` + `explode` pair, which covers more of RFC 6570-style templating. And 2.0 had no way to describe a cookie parameter at all; 3.0 adds `in: cookie`. ## New capabilities with no 2.0 equivalent `links` (describing how one operation's output feeds another's input) and `callbacks` (out-of-band requests the API makes back to the client, the basis for webhook description in 3.0) are both new. Neither has a 2.0 counterpart, so a conversion tool can only add them by hand. ## How conversion goes in practice Tools such as swagger2openapi handle the mechanical moves — servers, requestBody, components, `$ref` rewriting — reliably. What they cannot do is exploit the new expressiveness: splitting a single vague body schema into per-media-type schemas, introducing `oneOf` where the 2.0 document faked polymorphism with a loose object, or adding the `links` a hypermedia-aware client would want. Expect a converted document to be *valid* 3.0 and still read like 2.0 until someone edits it deliberately.
- Why can OpenAPI 3.0 describe an operation that accepts both JSON and CSV bodies when Swagger 2.0 could not?Because 3.0 keys the schema by media type inside `requestBody.content`. In 2.0 the accepted media types lived in a flat `consumes` list with a single `in: body` schema, so there was no way to bind a different schema to each type.
- What breaks in your tooling when you convert a 2.0 document to 3.0?Every hard-coded JSON pointer. `#/definitions/Pet` becomes `#/components/schemas/Pet`, and `#/parameters/...`, `#/responses/...` and `#/securityDefinitions/...` all move under `components` too. Scripts, fixtures and docs that referenced the old paths must be rewritten alongside the spec.
- How does a bearer-token security scheme differ between the two versions?Swagger 2.0 had no first-class bearer support — teams modelled it as an `apiKey` in the `Authorization` header. OpenAPI 3.0 expresses it properly as `type: http` with `scheme: bearer` and an optional `bearerFormat`, which is why converted documents often still carry the old apiKey workaround.
saying these in an interview costs you the question
- Calls it only a version-string change
- Thinks $ref paths survive the conversion
- Says host and basePath still exist in 3.0
- Believes 2.0 supported oneOf and anyOf
- Expects a converter to modernise the design too