Skip to content

Updated the project's README #129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,29 @@

[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/go-openapi/spec?status.svg)](http://godoc.org/github.com/go-openapi/spec)
[![GolangCI](https://golangci.com/badges/github.com/go-openapi/spec.svg)](https://golangci.com)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/spec)](https://goreportcard.com/report/github.com/go-openapi/spec)

The object model for OpenAPI specification documents.

Currently supports Swagger 2.0.
### FAQ

* What does this do?

> 1. This package knows how to marshal and unmarshal Swagger API specifications into a golang object model
> 2. It knows how to resolve $ref and expand them to make a single root documment

* How does it play with the rest of the go-openapi packages ?

> 1. This package is at the core of the go-openapi suite of packages and [code generator](https://github.com/go-swagger/go-swagger)
> 2. There is a [spec loading package](https://github.com/go-openapi/loads) to fetch specs as JSON or YAML from local or remote locations
> 3. There is a [spec validation package](https://github.com/go-openapi/validate) built on top of it
> 4. There is a [spec analysis package](https://github.com/go-openapi/analysis) built on top of it, to analyze, flatten, fix and merge spec documents

* Does this library support OpenAPI 3?

> No.
> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
> There is no plan to make it evolve toward supporting OpenAPI 3.x.
> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
>
> An early attempt to support Swagger 3 may be found at: https://github.com/go-openapi/spec3
6 changes: 3 additions & 3 deletions bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions contact_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ type ContactInfo struct {
VendorExtensible
}

// ContactInfoProps hold the properties of a ContactInfo object
type ContactInfoProps struct {
Name string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
Email string `json:"email,omitempty"`
}

// UnmarshalJSON hydrates ContactInfo from json
func (c *ContactInfo) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &c.ContactInfoProps); err != nil {
return err
}
return json.Unmarshal(data, &c.VendorExtensible)
}

// MarshalJSON produces ContactInfo as json
func (c ContactInfo) MarshalJSON() ([]byte, error) {
b1, err := json.Marshal(c.ContactInfoProps)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions license.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,21 @@ type License struct {
VendorExtensible
}

// LicenseProps holds the properties of a License object
type LicenseProps struct {
Name string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
}

// UnmarshalJSON hydrates License from json
func (l *License) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &l.LicenseProps); err != nil {
return err
}
return json.Unmarshal(data, &l.VendorExtensible)
}

// MarshalJSON produces License as json
func (l License) MarshalJSON() ([]byte, error) {
b1, err := json.Marshal(l.LicenseProps)
if err != nil {
Expand Down
9 changes: 9 additions & 0 deletions properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ import (
"sort"
)

// OrderSchemaItem holds a named schema (e.g. from a property of an object)
type OrderSchemaItem struct {
Name string
Schema
}

// OrderSchemaItems is a sortable slice of named schemas.
// The ordering is defined by the x-order schema extension.
type OrderSchemaItems []OrderSchemaItem

// MarshalJSON produces a json object with keys defined by the name schemas
// of the OrderSchemaItems slice, keeping the original order of the slice.
func (items OrderSchemaItems) MarshalJSON() ([]byte, error) {
buf := bytes.NewBuffer(nil)
buf.WriteString("{")
Expand Down Expand Up @@ -60,8 +65,11 @@ func (items OrderSchemaItems) Less(i, j int) (ret bool) {
return items[i].Name < items[j].Name
}

// SchemaProperties is a map representing the properties of a Schema object.
// It knows how to transform its keys into an ordered slice.
type SchemaProperties map[string]Schema

// ToOrderedSchemaItems transforms the map of properties into a sortable slice
func (properties SchemaProperties) ToOrderedSchemaItems() OrderSchemaItems {
items := make(OrderSchemaItems, 0, len(properties))
for k, v := range properties {
Expand All @@ -74,6 +82,7 @@ func (properties SchemaProperties) ToOrderedSchemaItems() OrderSchemaItems {
return items
}

// MarshalJSON produces properties as json, keeping their order.
func (properties SchemaProperties) MarshalJSON() ([]byte, error) {
if properties == nil {
return []byte("null"), nil
Expand Down
97 changes: 53 additions & 44 deletions spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,8 @@ func Test_Issue1429(t *testing.T) {
// assert well expanded
require.Truef(t, (sp.Paths != nil && sp.Paths.Paths != nil), "expected paths to be available in fixture")

for _, pi := range sp.Paths.Paths {
for _, param := range pi.Get.Parameters {
if assert.NotNilf(t, param.Schema, "expected param schema not to be nil") {
// all param fixtures are body param with schema
// all $ref expanded
assert.Equal(t, "", param.Schema.Ref.String())
}
}
for code, response := range pi.Get.Responses.StatusCodeResponses {
// all response fixtures are with StatusCodeResponses, but 200
if code == 200 {
assert.Nilf(t, response.Schema, "expected response schema to be nil")
continue
}
if assert.NotNilf(t, response.Schema, "expected response schema not to be nil") {
assert.Equal(t, "", response.Schema.Ref.String())
}
}
}
assertPaths1429(t, sp)

for _, def := range sp.Definitions {
assert.Equal(t, "", def.Ref.String())
}
Expand All @@ -103,48 +86,74 @@ func Test_Issue1429(t *testing.T) {
// assert well resolved
require.Truef(t, (sp.Paths != nil && sp.Paths.Paths != nil), "expected paths to be available in fixture")

assertPaths1429SkipSchema(t, sp)

for _, def := range sp.Definitions {
assert.Contains(t, def.Ref.String(), "responses.yaml#/")
}
}

func assertPaths1429(t testing.TB, sp *spec.Swagger) {
for _, pi := range sp.Paths.Paths {
for _, param := range pi.Get.Parameters {
if assert.NotNilf(t, param.Schema, "expected param schema not to be nil") {
// all param fixtures are body param with schema
if param.Name == "plainRequest" {
// this one is expanded
assert.Equal(t, "", param.Schema.Ref.String())
continue
}
if param.Name == "nestedBody" {
// this one is local
assert.Truef(t, strings.HasPrefix(param.Schema.Ref.String(), "#/definitions/"),
"expected rooted definitions $ref, got: %s", param.Schema.Ref.String())
continue
}
if param.Name == "remoteRequest" {
assert.Contains(t, param.Schema.Ref.String(), "remote/remote.yaml#/")
continue
}
assert.Contains(t, param.Schema.Ref.String(), "responses.yaml#/")
}
require.NotNilf(t, param.Schema, "expected param schema not to be nil")
// all param fixtures are body param with schema
// all $ref expanded
assert.Equal(t, "", param.Schema.Ref.String())
}

for code, response := range pi.Get.Responses.StatusCodeResponses {
// all response fixtures are with StatusCodeResponses, but 200
if code == 200 {
assert.Nilf(t, response.Schema, "expected response schema to be nil")
continue
}
if code == 204 {
assert.Contains(t, response.Schema.Ref.String(), "remote/remote.yaml#/")
require.NotNilf(t, response.Schema, "expected response schema not to be nil")
assert.Equal(t, "", response.Schema.Ref.String())
}
}
}

func assertPaths1429SkipSchema(t testing.TB, sp *spec.Swagger) {
for _, pi := range sp.Paths.Paths {
for _, param := range pi.Get.Parameters {
require.NotNilf(t, param.Schema, "expected param schema not to be nil")

// all param fixtures are body param with schema
switch param.Name {
case "plainRequest":
// this one is expanded
assert.Equal(t, "", param.Schema.Ref.String())
continue
case "nestedBody":
// this one is local
assert.Truef(t, strings.HasPrefix(param.Schema.Ref.String(), "#/definitions/"),
"expected rooted definitions $ref, got: %s", param.Schema.Ref.String())
continue
case "remoteRequest":
assert.Contains(t, param.Schema.Ref.String(), "remote/remote.yaml#/")
continue
}
if code == 404 {
assert.Contains(t, param.Schema.Ref.String(), "responses.yaml#/")

}

for code, response := range pi.Get.Responses.StatusCodeResponses {
// all response fixtures are with StatusCodeResponses, but 200
switch code {
case 200:
assert.Nilf(t, response.Schema, "expected response schema to be nil")
continue
case 204:
assert.Contains(t, response.Schema.Ref.String(), "remote/remote.yaml#/")
continue
case 404:
assert.Equal(t, "", response.Schema.Ref.String())
continue
}
assert.Containsf(t, response.Schema.Ref.String(), "responses.yaml#/", "expected remote ref at resp. %d", code)
}
}
for _, def := range sp.Definitions {
assert.Contains(t, def.Ref.String(), "responses.yaml#/")
}
}

func Test_MoreLocalExpansion(t *testing.T) {
Expand Down