libopenapi

A high-performance Go library for parsing, validating, mutating, bundling, and diffing OpenAPI 3.2/3.1/3.0, Swagger, Overlay, and Arazzo documents.

Library
Go
vv0.38.7
873stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
79/100Good
Development Activity68
Maintenance92
Community60
Maturity56
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture88
Code Quality90
Innovation85
Learning Curve68

libopenapi is a fully featured Go library for reading, validating, and manipulating OpenAPI 3.2, 3.1, and 3.0 specifications, plus Swagger (OpenAPI 2), Overlay, and Arazzo documents. It exposes two parallel APIs over the same parsed document: a high-level, mutable API for day-to-day reading and editing, and a low-level API that preserves the original YAML’s comments, line/column positions, and raw references for tooling that needs source fidelity.

Beyond parsing, libopenapi ships a full toolkit around specifications: a diff engine for detecting breaking changes between two versions of a document, a bundler for inlining or composing multi-file specs into one artifact, an indexing engine that resolves local and remote references and detects circular refs, and support for applying Overlay documents and running Arazzo workflows. It is the parsing engine behind several other pb33f tools, including vacuum, wiretap, and openapi-changes.

What You Get

  • Dual-layer document model - a high-level mutable API for everyday use and a low-level API (GoLow()) that preserves original YAML comments, line/column numbers, and raw references.
  • Built-in diff engine - the what-changed package compares two OpenAPI/Swagger documents and reports additions, removals, and breaking changes with configurable rules.
  • Reference resolution and circular detection - the index package (SpecIndex/Rolodex) resolves local and remote $refs, detects circular references, and supports multi-file specs.
  • Bundling and Overlay support - bundler inlines or composes multi-file specs into a single document, and overlay applies OpenAPI Overlay documents to a base spec.
  • Arazzo workflow support - parses, resolves, validates, and executes Arazzo workflow documents alongside standard OpenAPI specs.

Common Use Cases

  • Building OpenAPI-aware tooling - power linters, validators, or documentation generators (libopenapi is the engine behind vacuum, wiretap, and openapi-changes).
  • Detecting breaking API changes in CI - diff two versions of a spec on every pull request and fail the build when the change is breaking.
  • Bundling multi-file specifications for distribution - compose a spec split across many files/refs into one portable document before publishing it.
  • Programmatically mutating specs - read a document, add or modify paths and schemas via the high-level model, then re-render it back to YAML/JSON with RenderAndReload().

Under The Hood

Architecture libopenapi separates concerns into a low-level YAML-backed model layer (datamodel/low/) that preserves exact source fidelity — comments, line and column numbers, and raw references — and a high-level mutable facade layer (datamodel/high/) built on top of it via node_builder.go for rendering and re-serialization. Every high-level type exposes a GoLow() escape hatch back to the low model, a deliberate porcelain-vs-plumbing split documented in the package’s own AGENTS.md. The index/ package is the highest-risk, most central subsystem: SpecIndex and Rolodex own reference extraction, cross-document lookup, circular-reference detection, and $id resolution, with dedicated files for each concern (extract_refs.go, find_component_entry.go, resolver_entry.go). Bundling (bundler/), diffing (what-changed/), overlay application (overlay/), and Arazzo workflow support (arazzo/) are implemented as independent subsystems layered on top of the index and datamodel packages rather than folded into the root package, which document.go keeps intentionally thin as an orchestration-only entry point.

Tech Stack Built for Go 1.25 with an unusually small dependency footprint: pb33f/ordered-map for insertion-order-preserving maps used throughout the models, pb33f/jsonpath for JSONPath support, lucasjones/reggen for regex-based generation, go.yaml.in/yaml/v4 for YAML parsing, and golang.org/x/sync for concurrency primitives, plus a forked pb33f/testify for assertions. The library ships its own orderedmap/ and json/ packages rather than depending on third-party ordered-map or JSON-conversion libraries, reflecting a preference for owning core data-structure behavior. CI (.github/workflows/build.yaml) runs the full test suite on both Linux and Windows runners via GitHub Actions, with coverage uploaded to Codecov, and the generator/golang/ package adds first-class code-generation support for Go structs from OpenAPI schemas.

Code Quality Test coverage is extensive: hundreds of _test.go files sit alongside a comparable number of non-test source files, and CI enforces the suite on two operating systems with coverage tracked via Codecov. A search across the non-test codebase found no uses of panic() and abundant explicit error constructions, indicating errors are surfaced through Go’s standard error-return convention rather than swallowed or converted into panics. The presence of paired race_enabled.go/race_disabled.go files in datamodel/low/ shows deliberate handling of Go’s race detector across build tags. Naming is consistent, with low-level types mirroring their high-level counterparts, and reflection-driven model population is centralized and cached in datamodel/low/model_builder.go rather than duplicated per type.

API Design The defining design decision is exposing two parallel APIs over the same document: a high-level porcelain API (datamodel/high/) for everyday reading and mutation, and a low-level plumbing API (datamodel/low/) reachable from any high-level object via a uniform GoLow() method, giving access to original YAML comments, exact line/column positions, and raw references without sacrificing ergonomics for the common case. RenderAndReload() lets a consumer mutate the high-level model and get back both the re-serialized bytes and a rebuilt Document, closing a round-trip loop that many spec libraries leave to the caller. Getting started requires only NewDocument(bytes) followed by BuildV3Model() as shown in the README’s quick-start, and the project maintains its own documentation site covering indexing, resolution, bundling, diffing, and Arazzo separately from the README rather than cramming everything into one file.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search