Parsing Swagger Specifications
It's pretty old, but it's still important.Before we jump into the code, let’s get some context around Swagger with a very short history lesson.
The API wars
Swagger (Or now known affectionately as OpenAPI 2) first came onto the scene in 2012, which in tech years would make Swagger look like something built in the early 1900s.
Swagger/OpenAPI 2.0 emerged around 2014 and in 2015/2016 we saw a battle emerge between two competing standards, one is RAML (which was a product from MuleSoft) and the other was Swagger (which is a product from SmartBear).
Both RAML and Swagger went head to head with each other.
RAML had better features and a more elegant DSL, Swagger had better tools and a better community.
VHS vs. Betamax
The industry spoke loud and clear, we overwhelmingly chose Swagger. The wider reach and larger community of Swagger drove the adoption of the standard.
Swagger is reborn as OpenAPI
Because the industry settled on OpenAPI, we turned it into an actual standard called the OpenAPI initiative, separate from SmartBear.
OpenAPI 3.0 was the first release, it cleaned up a ton of mess from the legacy of Swagger’s design and aligned much closer with another community standard JSON Schema,
Parsing a Swagger Specification
libopenapi
contains two models, one for Swagger and one for OpenAPI. This is because they are so fundamentally different in
many places. To keep things cleaner we wrote separate Swagger models where they deviated from OpenAPI.
import (
"fmt"
"github.com/pb33f/libopenapi"
"github.com/pb33f/libopenapi/datamodel/high/v2"
"io/ioutil"
)
func main() {
// How to read in a Swagger / OpenAPI 2 Specification, into a Document.
// load a Swagger specification from bytes
petstore, _ := ioutil.ReadFile("petstorev2.json")
// create a new document from specification bytes
document, err := libopenapi.NewDocument(petstore)
// if anything went wrong, an error is thrown
if err != nil {
panic(fmt.Sprintf("cannot create new document: %e", err))
}
// define variables to capture the v2 model, or any errors thrown
var errors []error
var v2Model *libopenapi.DocumentModel[v2.Swagger]
// because we know this is a v2 spec,
// we can build a ready to go model from it.
v2Model, errors = document.BuildV2Model()
// if anything went wrong when building the v2 model,
// a slice of errors will be returned
if len(errors) > 0 {
for i := range errors {
fmt.Printf("error: %e\n", errors[i])
}
panic(fmt.Sprintf("cannot create v3 model from " +
"document: %d errors reported", len(errors)))
}
// get a count of the number of paths and schemas.
paths := len(v2Model.Model.Paths.PathItems)
schemas := len(v2Model.Model.Definitions.Definitions)
// print the number of paths and schemas in the document
fmt.Printf("There are %d paths and %d schemas" +
" in the document", paths, schemas)
}
Which will output:
Some friendly advice
Even though libopenapi
supports Swagger, we don’t recommend using it. It’s ancient and suffering from
bitrot in lots of tools the support it (not our tools of course)
Use, or start with OpenAPI instead of Swagger.