Giter Club home page Giter Club logo

openapi's Introduction

openapi - An OpenAPI 3.x library for go

Go Reference Latest Version Build Status

openapi is a library for parsing and validating OpenAPI 3.1, 3.0. The intent of the library is to offer building blocks for code and documentation generation.

โš ๏ธ This library is under active development; there may be breaking changes and bugs.

Features

  • $ref resolution
  • All keys retain their order from the markup using slices of key/values which aids in code generation.
  • Validation (see the validation section)
  • All non-primitive nodes have an absolute & relative location
  • Strings are text.Text which has case conversions and strings functions as methods.
  • Extensions, unknown JSON Schema keywords, examples, and a few other fields are instances of jsonx.RawMessage which comes with a few helper methods.
  • Supports both JSON and YAML

Usage

package main

import (
    "github.com/chanced/openapi"
    "github.com/chanced/uri"
    "github.com/santhosh-tekuri/jsonschema/v5"
    "embed"
    "io"
    "path/filepath"
    "log"
)

//go:embed spec
var specFiles embed.FS

func main() {
    ctx := context.Background()

    c, err := openapi.SetupCompiler(jsonschema.NewCompiler()) // adding schema files
    if err != nil {
        log.Fatal(err)
    }
    v, err := openapi.NewValidator(c)
    if err != nil {
        log.Fatal(err)
    }

    fn := func(_ context.Context, uri uri.URI, kind openapi.Kind) (openapi.Kind, []byte, error){
        f, err := specFiles.Open(fp)
        if err != nil {
            log.Fatal(err)
        }
        // you can return either JSON or YAML
        d, err := io.ReadAll(f)
        if err != nil{
            log.fatal(err)
        }
        // use the uri or the data to determine the Kind
        return openapi.KindDocument, d, nil
    }
    // you can Load either JSON or YAML
    // Load validates the Document as well.
    doc, err := openapi.Load(ctx, "spec/openapi.yaml", v, fn)
    if err != nil{
        log.Fatal(err)
    }
    _ = doc // *openapi.Document
}

Validation

The standard validator (StdValidator) currently validates OpenAPI documents with JSON Schema. Per OpenAPI's documentation, this may not be enough to properly encapsulate all the nuances of a specification. However, JSON Schema is able to successfully validate the current OpenAPI 3.1 Specification test suite.

Validation is an area that still needs work. If you do find cases where the current validator is not sufficient, please open an issue so that the library can be updated with proper coverage of that case.

Dependencies

Dependency Usage
github.com/santhosh-tekuri/jsonschema/v5 used in the StdValidator to validate OpenAPI documents & components
github.com/chanced/caps/text used for all string fields to provide case conversion and functions from strings as methods
github.com/chanced/jsonpointer relative locations of all non-scalar nodes
github.com/tidwall/gjson JSON parsing
github.com/chanced/jsonx raw JSON type and a toolkit for json type detection & parsing
github.com/chanced/maps small utility used to sort Extensions
github.com/chanced/transcode used to transform YAML into JSON and vice versa
github.com/chanced/uri used to represent URIs
github.com/Masterminds/semver openapi field and version detection of OpenAPI documents
gopkg.in/yaml.v3 needed to satisfy yaml.Marshaler and yaml.Unmarshaler
github.com/google/go-cmp testing purposes

Contributions

Please feel free to open up an issue or create a pull request if you find issues or if there are features you'd like to see added.

License

MIT

openapi's People

Contributors

chanced avatar undera avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

openapi's Issues

`$dynamicRef` / `$dynamicAnchor` resolution

Currently $dynamicRef does not override with the dynamic resolution. There are three issues at play:

  1. When loading a document, all nodes are parsed once and referenced when later encountered in $ref, $dynamicRef, $recursiveRef. This is fine for $ref except when the referenced schema has a $dynamicRef or $recursiveRef. In which case, those references need to be replaced with the schema containing the $dynamicAnchor. Currently, if the schema containing $dynamicRef were updated to the reflect the new $dynamicAnchor then it would happen across the application.

  2. $dynamicRefs are designed to be evaluated at runtime against data to ensure validity. This means that $dynamicAnchors can reside in conditional branches, such as if/then/else. Without data to compare against, there is no way of knowing which anchor to select.

  3. $dynamicRefs are transitive. This means that in a situation where:

    FileA has a $ref to FileB and the $dynamicAnchor T
    FileB has a $ref to FileC
    FileC has a $dynamicRef #T

In order to solve dynamic overlay, after the document is loaded and resolved, every schema is going to need to be cloned and reassigned. Use a map of AbsoluteLocation of the SchemaRef to ensure that a reference hasn't been visited in the cloning process.

I have no idea how to solve conditional/dynamic resolution.

The solution to the third depends on how the second is solved.

Duplicate anchors should not return an error

If there are duplicate named anchors within the same file, an error is returned. This is not up to spec.

It was added to try and allow $dynamicRef but those are transitive anyway so it doesn't matter.

Examples and Example in ParameterObj

Hello,

Thanks for your nice library, it's a rare project that supports OAS 3.1

I have a question about examples fields in parameters. In OAS Spec I see that there can be 2 options to specify examples (https://spec.openapis.org/oas/v3.1.0#fixed-fields-9): example and examples, mutually exclusive.

In the ParameterObj I only see the Examples field. Trying to load the following document with library gives no access to example value:

{
  "openapi": "3.1.0",
  "info": {
    "title": "",
    "version": ""
  },
  "paths": {
    "/catalogue/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "schema": {
            "type": "string"
          },
          "example": "some-uuid-maybe"
        }
      ]
    }
  }
}

Is there a plan to support the example, as defined in OAS 3.1 specification?

Unable to load valid OAS

The following code fails with message Failed: json: cannot unmarshal object into Go struct field openapi.paths of type openapi.Example. The spec is quite simple and valid, as far as I can see...

func TestLoadData(t *testing.T) {
	data := `{
	  "openapi": "3.1.0",
	  "info": {
		"title": "",
		"version": "",
		"description": "Test file for loading pre-existing OAS"
	  },
	  "paths": {
		"/catalogue/{id}": {
		  "parameters": [
			{
			  "name": "id",
			  "in": "path",
			  "required": true,
			  "style": "simple",
			  "schema": {
				"type": "string"
			  },
			  "examples": {
				"an example": {
				  "value": "someval"
				}
			  }
			}
		  ]
		},
		"/catalogue/{id}/details": {
		  "parameters": [
			{
			  "name": "id",
			  "in": "path",
			  "style": "simple",
			  "required": true,
			  "schema": {
				"type": "string"
			  },
			  "example": "some-uuid-maybe"
			}
		  ]
		}
	  }
	}`

	var oas openapi.OpenAPI
	err := json.Unmarshal([]byte(data), &oas)
	if err != nil {
		t.Errorf("Failed: %s", err)
		t.FailNow()
	}
}

MarshalYAML is not producing proper results

All MarshalYAML methods are not producing proper results. MarshalYAML does not detect whether the result is a slice of bytes and so it is marshaling the bytes as an array.

This does not effect Load.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.