Note: All code has been generated by Claude Code using claude-4-5-sonnet
OpenAPI Specification (OAS) tools for validation, parsing, converting, and joining.

Features
- Validate - Validate OpenAPI specification files for correctness
- Parse - Parse and analyze OpenAPI specifications
- Convert - Convert OpenAPI specifications between different versions (2.0 ↔ 3.x)
- Join - Join multiple OpenAPI Specification documents
- Library - Use as a Go library in your own applications
When converting or joining OpenAPI specifications, oastools automatically preserves the input file format:
- JSON input → JSON output: If your source file is in JSON format, the converted or joined output will also be in JSON format
- YAML input → YAML output: If your source file is in YAML format, the converted or joined output will also be in YAML format
This ensures format consistency across your toolchain and makes it easier to maintain version-controlled API specifications.
Example:
# Convert a JSON file - output will also be JSON
oastools convert -t 3.0.3 swagger.json -o openapi.json
# Convert a YAML file - output will also be YAML
oastools convert -t 3.0.3 swagger.yaml -o openapi.yaml
# Join JSON files - output will be JSON (format from first file)
oastools join -o merged.json api1.json api2.json
Supported OpenAPI Specification Versions
This tool supports all official OpenAPI Specification releases:
Note: Release candidate versions (e.g., 3.0.0-rc0, 3.1.0-rc1) are detected but not officially supported.
Installation
From Source
git clone https://github.com/erraggy/oastools.git
cd oastools
make install
Using Go
go install github.com/erraggy/oastools/cmd/oastools@latest
As a Library
go get github.com/erraggy/oastools@latest
Usage
Command-Line Interface
# Show help
oastools help
# Validate an OpenAPI spec
oastools validate openapi.yaml
# Parse an OpenAPI spec
oastools parse openapi.yaml
# Convert between OpenAPI versions
oastools convert -t 3.0.3 swagger.yaml -o openapi.yaml
# Join multiple OpenAPI specs
oastools join -o merged.yaml base.yaml extensions.yaml
Library Usage
The library provides two API styles for different use cases:
Simple API (Convenience Functions)
For quick, one-off operations, use the package-level convenience functions:
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/parser"
"github.com/erraggy/oastools/validator"
"github.com/erraggy/oastools/converter"
"github.com/erraggy/oastools/joiner"
)
func main() {
// Parse an OpenAPI specification
result, err := parser.Parse("openapi.yaml", false, true)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Version: %s\n", result.Version)
// Validate an OpenAPI specification
vResult, err := validator.Validate("openapi.yaml", true, false)
if err != nil {
log.Fatal(err)
}
if !vResult.Valid {
fmt.Printf("Found %d errors\n", vResult.ErrorCount)
}
// Convert between OpenAPI versions
cResult, err := converter.Convert("swagger.yaml", "3.0.3")
if err != nil {
log.Fatal(err)
}
if cResult.HasCriticalIssues() {
fmt.Printf("Conversion completed with %d critical issue(s)\n", cResult.CriticalCount)
}
// Join multiple OpenAPI specifications
config := joiner.DefaultConfig()
config.PathStrategy = joiner.StrategyAcceptLeft
jResult, err := joiner.Join([]string{"base.yaml", "extensions.yaml"}, config)
if err != nil {
log.Fatal(err)
}
// Write the result using a Joiner instance
j := joiner.New(config)
err = j.WriteResult(jResult, "merged.yaml")
if err != nil {
log.Fatal(err)
}
}
Advanced API (Reusable Instances)
For processing multiple files with the same configuration, create reusable instances:
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/parser"
"github.com/erraggy/oastools/validator"
"github.com/erraggy/oastools/converter"
"github.com/erraggy/oastools/joiner"
)
func main() {
// Create a parser instance for reuse
p := parser.New()
p.ResolveRefs = false
p.ValidateStructure = true
result1, _ := p.Parse("api1.yaml")
result2, _ := p.Parse("api2.yaml")
result3, _ := p.Parse("api3.yaml")
fmt.Printf("Parsed %d files\n", 3)
// Create a validator instance for reuse
v := validator.New()
v.IncludeWarnings = true
v.StrictMode = false
vResult1, _ := v.Validate("api1.yaml")
vResult2, _ := v.Validate("api2.yaml")
// Create a converter instance for reuse
c := converter.New()
c.StrictMode = false
c.IncludeInfo = true
cResult1, _ := c.Convert("swagger-v1.yaml", "3.0.3")
cResult2, _ := c.Convert("swagger-v2.yaml", "3.0.3")
// Create a joiner instance for reuse
config := joiner.DefaultConfig()
config.SchemaStrategy = joiner.StrategyAcceptLeft
j := joiner.New(config)
jResult1, _ := j.Join([]string{"api1-base.yaml", "api1-ext.yaml"})
jResult2, _ := j.Join([]string{"api2-base.yaml", "api2-ext.yaml"})
j.WriteResult(jResult1, "merged-api1.yaml")
j.WriteResult(jResult2, "merged-api2.yaml")
}
For complete API documentation, see pkg.go.dev.
Example Usage
go run github.com/erraggy/oastools/cmd/oastools validate testdata/invalid-oas3.yaml
OpenAPI Specification Validator
================================
File: testdata/invalid-oas3.yaml
Version: 3.0.3
Errors (12):
✗ document: oas 3.0.3: missing required field 'info.version': Info object must have a version string per spec
✗ document: oas 3.0.3: invalid path pattern 'paths.items': path must begin with '/'
✗ document: oas 3.0.3: missing required field 'paths.items.get.responses': Operation must have a responses object
✗ document: oas 3.0.3: invalid parameter 'paths.items.get.parameters[0]': path parameters must have 'required: true' per spec
✗ document: oas 3.0.3: missing required field 'paths.items.get.parameters[1].in': Parameter must specify location (query, header, path, cookie)
✗ document: oas 3.0.3: missing required field 'paths.items.post.requestBody.content': RequestBody must have at least one media type
✗ document: oas 3.0.3: duplicate operationId 'createItem' at 'paths./users.get': previously defined at 'paths.items.post' (operationIds must be unique across all operations)
✗ info.version: Info object must have a version
Spec: https://spec.openapis.org/oas/v3.0.3.html#info-object
✗ paths.items: Path must start with '/'
Spec: https://spec.openapis.org/oas/v3.0.3.html#paths-object
✗ paths.items.post.requestBody: RequestBody must have a content object with at least one media type
Spec: https://spec.openapis.org/oas/v3.0.3.html#request-body-object
✗ paths.items.get.parameters[0]: Path parameters must have required: true
Spec: https://spec.openapis.org/oas/v3.0.3.html#parameter-object
✗ paths.items.post: Duplicate operationId 'createItem' (first seen at paths./users.get)
Spec: https://spec.openapis.org/oas/v3.0.3.html#operation-object
Warnings (3):
⚠ paths.items.post: Operation should have a description or summary for better documentation
Spec: https://spec.openapis.org/oas/v3.0.3.html#operation-object
⚠ paths./users.get: Operation should have a description or summary for better documentation
Spec: https://spec.openapis.org/oas/v3.0.3.html#operation-object
⚠ paths.items.get: Parameter 'id' is declared as path parameter but not used in path template
Spec: https://spec.openapis.org/oas/v3.0.3.html#path-item-object
✗ Validation failed: 12 error(s), 3 warning(s)
exit status 1
Limitations
External References
- HTTP(S) References Not Supported: The parser currently only supports local file references for external
$ref values. References starting with http:// or https:// are not yet supported.
- Security: External file references are restricted to the base directory and its subdirectories to prevent path traversal attacks.
Development
Prerequisites
- Go 1.24 or higher
- make (optional, but recommended)
Building
# Build the binary
make build
# Run tests
make test
# Run linter
make lint
# Format code
make fmt
Project Structure
.
├── cmd/oastools/ # CLI entry point
├── parser/ # OpenAPI parsing library
├── validator/ # OpenAPI validation library
├── converter/ # OpenAPI version conversion library
├── joiner/ # OpenAPI joining library
└── testdata/ # Test fixtures and sample specs
All four packages (parser, validator, converter, joiner) are public and can be imported
directly in your Go applications.
License
MIT