OpenAPI 3.0 / 3.1 Compatibility
Soxom accepts both OpenAPI 3.0 and 3.1 specs and ships six generators: Python, Java, Go, TypeScript, Ruby, and C#.
Go, TypeScript, and Python are at near-full coverage of both versions.
Java and Ruby are close behind — Java models the full operation /
parameter / auth / content-type surface plus Bean Validation
constraints, and Ruby covers the same breadth minus a few schema-level
validation keywords. C# is the newest generator: it covers most of the
surface (all auth schemes, every parameter style, multipart / octet
bodies, discriminated unions) but does not yet model document-level
servers, response headers, status-code ranges, tags, or x-*
extensions.
When a generator encounters a keyword it cannot fully model in the target language, it does not fail the build (with one exception — see the note on C# below). Instead it:
- Emits a diagnostic line to the build log naming the feature and the JSON pointer where it appeared.
- Falls back to the language’s untyped escape hatch (
any,Object,interface{},JsonElement, …) so the rest of the SDK still generates.
Diagnostic conventions differ by generator:
- Python, Java, Go, TypeScript emit the uniform
[soxom:warn] unsupported OpenAPI feature '<name>' at <pointer>line. - C# emits coded diagnostics (
SOX004,SOX005,SOX006, …) atinfo/warninglevel instead of the[soxom:warn]prefix, and its parser (Microsoft.OpenApi) is strict — a spec with an invalid enum value (e.g. a bogus parameterstyle) is rejected outright rather than warned-and-degraded. - Ruby does not emit a per-feature warning line; schema keywords it cannot model are accepted silently (the generated type still builds, the constraint is simply not enforced). A run-level summary is printed to stderr.
Use the matrix below to see what to expect per generator.
Legend
Section titled “Legend”- ✅ Full — the feature shapes the generated code.
- ⚠️ Degraded — recognised; falls back to
any/Object/interface{}/JsonElement(and warns, except in Ruby). - ❌ Silently dropped — not modelled; the field/keyword is omitted with no diagnostic.
Feature matrix
Section titled “Feature matrix”JSON Schema keywords (3.0 + 3.1)
Section titled “JSON Schema keywords (3.0 + 3.1)”| Feature | 3.0 form | 3.1 form | Python | Java | Go | TypeScript | Ruby | C# |
|---|---|---|---|---|---|---|---|---|
| Nullable type | nullable: true | type: ["string", "null"] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
examples (array) | example (single) | examples: [...] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Exclusive bounds | exclusiveMaximum: true + maximum | exclusiveMaximum: 100 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
String constraints (pattern, minLength, maxLength) | same | same | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
Numeric constraints (minimum, maximum, multipleOf) | same | same | ✅ | ✅ | ✅ | ✅ | ⚠️ Ⓡ | ❌ |
Array constraints (minItems, maxItems, uniqueItems) | same | same | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
Object constraints (minProperties, maxProperties) | same | same | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
default values | same | same | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
readOnly / writeOnly | same | same | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
deprecated (schema / operation / parameter) | same | same | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Typed formats (uuid, email, uri, ipv4, ipv6, byte, int32) | same | same | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
const | — | const: "v1" | ✅ | ✅ | ✅ | ✅ † | ✅ | ✅ |
prefixItems (tuple) | — | prefixItems: [...] | ✅ | ⚠️ | ⚠️ | ✅ | ✅ | ⚠️ |
dependentRequired | — | dependentRequired: {...} | ✅ | ✅ | ⚠️ | ✅ § | ❌ | ⚠️ |
dependentSchemas | — | dependentSchemas: {...} | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ❌ | ⚠️ |
unevaluatedProperties | — | unevaluatedProperties: false | ✅ | ✅ | ⚠️ | ✅ ¶ | ❌ | ⚠️ |
if/then/else | — | if: ... then: ... else: ... | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ❌ | ⚠️ |
$dynamicRef / $dynamicAnchor | — | $dynamicRef: "#node" | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ❌ | ❌ |
$ref with siblings | Sibling keywords ignored | Sibling keywords honoured | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ |
patternProperties | — | patternProperties: {...} | ✅ ‖ | ✅ ‖ | ✅ ‖ | ✅ ‖ | ❌ | ⚠️ |
Operations, parameters, content types
Section titled “Operations, parameters, content types”| Feature | Python | Java | Go | TypeScript | Ruby | C# |
|---|---|---|---|---|---|---|
Parameters: in: query / in: path | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Parameters: in: header | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Parameters: in: cookie | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Path-item-level parameter merging | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Parameter style / explode (all 7 styles) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Parameter allowEmptyValue | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Request body: application/json | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Request body: multipart/form-data (file uploads) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ Ⓒ |
Request body: application/x-www-form-urlencoded | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Request body: application/octet-stream | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ Ⓒ |
Request body: application/xml / text/plain | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| Multi-content-type request bodies | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
Multipart encoding object (per-part headers/content-type) | ✅ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ |
Response body: application/json | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Response body: binary / application/octet-stream | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Response body: text/event-stream (SSE) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Response status: range codes (2XX/4XX/5XX) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
Response status: default (typed errors) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Response headers (typed) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Typed error responses (4xx/5xx body schemas) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Document-level features
Section titled “Document-level features”| Feature | Python | Java | Go | TypeScript | Ruby | C# |
|---|---|---|---|---|---|---|
Multiple servers | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
Server variables (URL templating) | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
Per-path / per-operation servers | ⚠️ | ✅ | ✅ | ✅ | ✅ | ❌ |
components.securitySchemes (apiKey, http, oauth2, openIdConnect, mutualTLS) | ✅ | ✅ | ✅ | ✅ | ✅ Ⓜ | ✅ Ⓜ |
Global / per-operation security (AND/OR + opt-out) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| OAuth2 client-credentials flow (built-in TokenSource) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| OAuth2 authorization-code / implicit / password flows | ⚠️ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
$ref to non-schema components (parameters, responses, requestBodies, …) | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ |
3.1 components.pathItems | ✅ | ⚠️ | ✅ | ✅ | ❌ | ⚠️ |
info.contact / info.license / info.termsOfService | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
Document-level externalDocs | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
tags (definitions + per-operation) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
operationId collision detection | ❌ | ✅ | ✅ | ✅ | ⚠️ | ❌ |
Vendor extensions (x-*) surfaced to SDK doc-comments | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
callbacks on operations (typed receivers) | ⚠️ | ⚠️ | ✅ | ✅ ‡ | ⚠️ | ❌ |
3.1 top-level webhooks (typed receivers + Mux) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
response.links / components.links | ❌ | ⚠️ | ⚠️ | ✅ | ❌ | ❌ |
The ⚠️ rows are tracked for future work — open an issue if a specific keyword is blocking you and we’ll prioritise it.
† TypeScript const support covers primitive values (string, number, boolean,
null). Object- and array-valued const still falls back to unknown.
‡ TypeScript exposes callbacks as a typed escape hatch — the SDK emits
payload types you can use in your own webhook handler — rather than the
runtime mux/dispatcher pattern the Go generator uses.
§ TypeScript surfaces dependentRequired as a @dependentRequired JSDoc tag
on the generated interface plus an opt-in validate<TypeName>(obj) runtime
helper that throws ValidationError if the constraint is violated. The
generator never auto-invokes the validator — call it from your own ingest
path when you want stricter runtime checks.
¶ TypeScript handles the unevaluatedProperties: false form (extra properties
are forbidden). The generated interface emits a @strictProperties JSDoc
tag and an opt-in validate<TypeName> runtime helper. The typed form
(unevaluatedProperties: { type: ... }) still warns and degrades — it
requires composition-aware validation that the opt-in helper does not cover.
‖ Single-regex patternProperties (one pattern, no fixed properties) is
lifted to the language’s open-map type (Record<string, T> / map[string]T
/ Map<String, V> / dict[str, T]). Multi-pattern objects can’t carry
per-regex value shapes in a static type, so they degrade. Ruby does not
model patternProperties at all; C# degrades it with a SOX006 diagnostic.
Ⓡ Ruby surfaces numeric minimum / maximum / exclusive bounds as YARD doc
tags only (not multipleOf), and emits no runtime constraint validation.
String, array, and object constraints are not modelled.
Ⓒ C# multipart and octet-stream request bodies are runtime-verified by the
conformance suite, but the emitter marks them with a SOX008 “partial
support” info diagnostic — exotic per-part encodings may not round-trip.
Ⓜ mutualTLS: Python, Go, and TypeScript wire client certificates into the
HTTP client directly. Ruby warns and expects you to configure the SSL
context yourself; C# applies the scheme via default request headers.
What a degraded-feature diagnostic looks like
Section titled “What a degraded-feature diagnostic looks like”For Python, Java, Go, and TypeScript, every degraded feature produces a stderr line in this format:
[soxom:warn] unsupported OpenAPI feature 'prefixItems' at #/components/schemas/Point/properties/coordinateC# emits coded diagnostics instead:
warning: [SOX006] unsupported keyword `dependentRequired`; emitted type may be degraded (at #/components/schemas/Order/dependentRequired)These lines surface in the live build log viewer and in your build’s stored log output. They do not count as build failures. (A C# build can fail if the spec itself is invalid — see the strict-parser note above.)
Verifying compatibility on your spec
Section titled “Verifying compatibility on your spec”Pushing a spec to your Config Repository runs all enabled generators. Search
the build log for [soxom:warn] (or SOX0 for C#) to see which features
were degraded. If you need a clean run, switch the offending schema to a
2020-12-equivalent form that uses only supported keywords (often oneOf
plus discriminator works in place of conditional schemas).
Roadmap
Section titled “Roadmap”Real handling of the remaining ⚠️/❌ keywords (dependentSchemas,
if/then/else, $dynamicRef, multi-pattern patternProperties) and
cross-generator parity for the newer Ruby and C# columns is tracked on the
generator roadmap. The degrade-and-continue
behaviour above is the floor — generators graduate features from ⚠️ to ✅ as
we add real codegen support.