zoobzio January 6, 2025 Edit this page

Quick Start

Building a Specification

Construct specs using struct literals. Start with the root OpenAPI type and populate the fields you need:

package main

import (
    "github.com/zoobz-io/openapi"
)

func main() {
    spec := &openapi.OpenAPI{
        OpenAPI: "3.1.0",
        Info: openapi.Info{
            Title:       "Bookstore API",
            Version:     "1.0.0",
            Description: "API for managing books",
        },
        Servers: []openapi.Server{
            {URL: "https://api.bookstore.example.com"},
        },
        Paths: map[string]openapi.PathItem{
            "/books": {
                Get: &openapi.Operation{
                    Summary:     "List books",
                    OperationID: "listBooks",
                    Responses: map[string]openapi.Response{
                        "200": {Description: "Book list"},
                    },
                },
            },
        },
    }
    _ = spec
}

Reading Existing Specs

Parse JSON or YAML specs into Go types:

// From JSON
data, _ := os.ReadFile("api.json")
spec, err := openapi.FromJSON(data)
if err != nil {
    log.Fatal(err)
}

// From YAML
data, _ := os.ReadFile("api.yaml")
spec, err := openapi.FromYAML(data)
if err != nil {
    log.Fatal(err)
}

// Access fields directly
fmt.Println(spec.Info.Title)
for path, item := range spec.Paths {
    if item.Get != nil {
        fmt.Printf("GET %s: %s\n", path, item.Get.Summary)
    }
}

Writing Specs

Serialize specs to JSON or YAML:

// To JSON
jsonBytes, err := spec.ToJSON()
os.WriteFile("api.json", jsonBytes, 0644)

// To YAML
yamlBytes, err := spec.ToYAML()
os.WriteFile("api.yaml", yamlBytes, 0644)

// Or use standard marshallers directly
json.NewEncoder(os.Stdout).Encode(spec)
yaml.NewEncoder(os.Stdout).Encode(spec)

Working with Schemas

Schemas represent JSON Schema objects. Use NewSchemaType to set the type field:

// Simple types
stringSchema := &openapi.Schema{
    Type: openapi.NewSchemaType("string"),
}

// Nullable types (OpenAPI 3.1 style)
nullableString := &openapi.Schema{
    Type: openapi.NewSchemaTypes([]string{"string", "null"}),
}

// Object with properties
userSchema := &openapi.Schema{
    Type: openapi.NewSchemaType("object"),
    Properties: map[string]*openapi.Schema{
        "id":    {Type: openapi.NewSchemaType("integer")},
        "email": {Type: openapi.NewSchemaType("string"), Format: "email"},
    },
    Required: []string{"id", "email"},
}

// Array of references
usersSchema := &openapi.Schema{
    Type:  openapi.NewSchemaType("array"),
    Items: &openapi.Schema{Ref: "#/components/schemas/User"},
}

Using References

Reference reusable components with the Ref field:

spec := &openapi.OpenAPI{
    // ... info, paths ...
    Components: &openapi.Components{
        Schemas: map[string]*openapi.Schema{
            "Error": {
                Type: openapi.NewSchemaType("object"),
                Properties: map[string]*openapi.Schema{
                    "code":    {Type: openapi.NewSchemaType("integer")},
                    "message": {Type: openapi.NewSchemaType("string")},
                },
            },
        },
        Responses: map[string]*openapi.Response{
            "NotFound": {
                Description: "Resource not found",
                Content: map[string]openapi.MediaType{
                    "application/json": {
                        Schema: &openapi.Schema{Ref: "#/components/schemas/Error"},
                    },
                },
            },
        },
    },
}

// Reference in an operation
operation := &openapi.Operation{
    Responses: map[string]openapi.Response{
        "404": {Ref: "#/components/responses/NotFound"},
    },
}

Security Schemes

Define authentication methods in components:

spec.Components = &openapi.Components{
    SecuritySchemes: map[string]*openapi.SecurityScheme{
        "bearerAuth": {
            Type:         "http",
            Scheme:       "bearer",
            BearerFormat: "JWT",
        },
        "apiKey": {
            Type: "apiKey",
            Name: "X-API-Key",
            In:   "header",
        },
    },
}

// Apply globally
spec.Security = []openapi.SecurityRequirement{
    {"bearerAuth": {}},
}

// Or per-operation
operation.Security = []openapi.SecurityRequirement{
    {"apiKey": {}},
}