Skip to content

Commit

Permalink
yaml convertes
Browse files Browse the repository at this point in the history
  • Loading branch information
hedhyw committed Mar 13, 2022
1 parent cb19249 commit 22b0d67
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 23 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v2 v2.4.0
sigs.k8s.io/yaml v1.3.0
)

Expand All @@ -21,5 +22,4 @@ require (
golang.org/x/text v0.3.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.6 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
6 changes: 3 additions & 3 deletions protoc-gen-openapiv2/internal/genopenapi/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -1891,7 +1891,7 @@ func processHeaders(inputHdrs map[string]*openapi_options.Header) (openapiHeader
if err != nil {
return nil, err
}
ret.Default = json.RawMessage(v.Default)
ret.Default = RawExample(v.Default)
}
hdrs[header] = ret
}
Expand Down Expand Up @@ -2396,7 +2396,7 @@ func updateswaggerObjectFromJSONSchema(s *openapiSchemaObject, j *openapi_option
s.Type = strings.ToLower(overrideType[0].String())
}
if j != nil && j.GetExample() != "" {
s.Example = json.RawMessage(j.GetExample())
s.Example = RawExample(j.GetExample())
}
if j != nil && j.GetFormat() != "" {
s.Format = j.GetFormat()
Expand Down Expand Up @@ -2438,7 +2438,7 @@ func openapiSchemaFromProtoSchema(s *openapi_options.Schema, reg *descriptor.Reg
updateswaggerObjectFromJSONSchema(&ret, s.GetJsonSchema(), reg, data)

if s != nil && s.Example != "" {
ret.Example = json.RawMessage(s.Example)
ret.Example = RawExample(s.Example)
}

return ret
Expand Down
10 changes: 5 additions & 5 deletions protoc-gen-openapiv2/internal/genopenapi/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1807,19 +1807,19 @@ func TestApplyTemplateHeaders(t *testing.T) {
"Boolean": openapiHeaderObject{
Description: "boolean header description",
Type: "boolean",
Default: json.RawMessage("true"),
Default: RawExample("true"),
Pattern: "^true|false$",
},
"Integer": openapiHeaderObject{
Description: "integer header description",
Type: "integer",
Default: json.RawMessage("0"),
Default: RawExample("0"),
Pattern: "^[0-9]$",
},
"Number": openapiHeaderObject{
Description: "number header description",
Type: "number",
Default: json.RawMessage("1.2"),
Default: RawExample("1.2"),
Pattern: "^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$",
},
},
Expand Down Expand Up @@ -4193,7 +4193,7 @@ func TestRenderMessagesAsDefinition(t *testing.T) {
defs: map[string]openapiSchemaObject{
"Message": {schemaCore: schemaCore{
Type: "object",
Example: json.RawMessage(`{"foo":"bar"}`),
Example: RawExample(`{"foo":"bar"}`),
}},
},
},
Expand All @@ -4210,7 +4210,7 @@ func TestRenderMessagesAsDefinition(t *testing.T) {
defs: map[string]openapiSchemaObject{
"Message": {schemaCore: schemaCore{
Type: "object",
Example: json.RawMessage(`XXXX anything goes XXXX`),
Example: RawExample(`XXXX anything goes XXXX`),
}},
},
},
Expand Down
61 changes: 47 additions & 14 deletions protoc-gen-openapiv2/internal/genopenapi/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"

"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor"
"gopkg.in/yaml.v2"
)

type param struct {
Expand Down Expand Up @@ -53,8 +54,8 @@ type openapiExternalDocumentationObject struct {
}

type extension struct {
key string
value json.RawMessage
key string `json:"-" yaml:"-"`
value json.RawMessage `json:"-" yaml:"-"`
}

// http://swagger.io/specification/#swaggerObject
Expand Down Expand Up @@ -90,7 +91,7 @@ type openapiSecuritySchemeObject struct {
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
Scopes openapiScopesObject `json:"scopes,omitempty" yaml:"scopes,omitempty"`

extensions []extension
extensions []extension `json:"-" yaml:"-"`
}

// http://swagger.io/specification/#scopesObject
Expand Down Expand Up @@ -158,11 +159,11 @@ type openapiParameterObject struct {
// supported by generation tools such as swagger-codegen and go-swagger.
// For protoc-gen-openapiv3, we'd want to add `nullable` instead.
type schemaCore struct {
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Format string `json:"format,omitempty" yaml:"format,omitempty"`
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
XNullable bool `json:"x-nullable,omitempty" yaml:"x-nullable,omitempty"`
Example json.RawMessage `json:"example,omitempty" yaml:"example,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Format string `json:"format,omitempty" yaml:"format,omitempty"`
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
XNullable bool `json:"x-nullable,omitempty" yaml:"x-nullable,omitempty"`
Example RawExample `json:"example,omitempty" yaml:"example,omitempty"`

Items *openapiItemsObject `json:"items,omitempty" yaml:"items,omitempty"`

Expand All @@ -173,6 +174,25 @@ type schemaCore struct {
Default string `json:"default,omitempty" yaml:"default,omitempty"`
}

type RawExample json.RawMessage

func (m RawExample) MarshalJSON() ([]byte, error) {
return (json.RawMessage)(m).MarshalJSON()
}

func (m *RawExample) UnmarshalJSON(data []byte) error {
return (*json.RawMessage)(m).UnmarshalJSON(data)
}

func (e RawExample) MarshalYAML() (interface{}, error) {
var data interface{}
if err := json.Unmarshal(e, &data); err != nil {
return nil, err
}

return data, nil
}

func (s *schemaCore) setRefFromFQN(ref string, reg *descriptor.Registry) error {
name, ok := fullyQualifiedNameToOpenAPIName(ref, reg)
if !ok {
Expand Down Expand Up @@ -201,11 +221,11 @@ type openapiHeadersObject map[string]openapiHeaderObject

// http://swagger.io/specification/#headerObject
type openapiHeaderObject struct {
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Format string `json:"format,omitempty" yaml:"format,omitempty"`
Default json.RawMessage `json:"default,omitempty" yaml:"default,omitempty"`
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Format string `json:"format,omitempty" yaml:"format,omitempty"`
Default RawExample `json:"default,omitempty" yaml:"default,omitempty"`
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
}

type keyVal struct {
Expand All @@ -215,6 +235,19 @@ type keyVal struct {

type openapiSchemaObjectProperties []keyVal

func (p openapiSchemaObjectProperties) MarshalYAML() (interface{}, error) {
ms := make(yaml.MapSlice, len(p))

for i, v := range p {
ms[i] = yaml.MapItem{
Key: v.Key,
Value: v.Value,
}
}

return ms, nil
}

func (op openapiSchemaObjectProperties) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
buf.WriteString("{")
Expand All @@ -241,7 +274,7 @@ func (op openapiSchemaObjectProperties) MarshalJSON() ([]byte, error) {

// http://swagger.io/specification/#schemaObject
type openapiSchemaObject struct {
schemaCore
schemaCore `yaml:",inline"`
// Properties can be recursively defined
Properties *openapiSchemaObjectProperties `json:"properties,omitempty" yaml:"properties,omitempty"`
AdditionalProperties *openapiSchemaObject `json:"additionalProperties,omitempty" yaml:"additionalProperties,omitempty"`
Expand Down
108 changes: 108 additions & 0 deletions protoc-gen-openapiv2/internal/genopenapi/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package genopenapi

import (
"encoding/json"
"strings"
"testing"

"gopkg.in/yaml.v2"
)

func newSpaceReplacer() *strings.Replacer {
return strings.NewReplacer(" ", "", "\n", "", "\t", "")
}

func TestRawExample(t *testing.T) {
t.Parallel()

testCases := [...]struct {
In RawExample
Exp string
}{{
In: RawExample(`1`),
Exp: `1`,
}, {
In: RawExample(`"1"`),
Exp: `"1"`,
}, {
In: RawExample(`{"hello":"worldr"}`),
Exp: "hello:\n" +
" worldr\n",
}}

sr := newSpaceReplacer()

for _, tc := range testCases {
tc := tc

t.Run(string(tc.In), func(t *testing.T) {
t.Parallel()

ex := RawExample(tc.In)

out, err := yaml.Marshal(ex)
switch {
case err != nil:
t.Fatalf("expect no yaml marshal error, got: %s", err)
case !json.Valid(tc.In):
t.Fatalf("json is invalid: %#q", tc.In)
case sr.Replace(tc.Exp) != sr.Replace(string(out)):
t.Fatalf("expected: %s, actual: %s", tc.Exp, out)
}

out, err = json.Marshal(tc.In)
switch {
case err != nil:
t.Fatalf("expect no json marshal error, got: %s", err)
case sr.Replace(string(tc.In)) != sr.Replace(string(out)):
t.Fatalf("expected: %s, actual: %s", tc.In, out)
}
})
}
}

func TestOpenapiSchemaObjectProperties(t *testing.T) {
t.Parallel()

v := map[string]interface{}{
"example": openapiSchemaObjectProperties{{
Key: "test1",
Value: 1,
}, {
Key: "test2",
Value: 2,
}},
}

t.Run("yaml", func(t *testing.T) {
t.Parallel()

const exp = "example:\n" +
" test1: 1\n" +
" test2: 2\n"

sr := newSpaceReplacer()

out, err := yaml.Marshal(v)
switch {
case err != nil:
t.Fatalf("expect no marshal error, got: %s", err)
case sr.Replace(exp) != sr.Replace(string(out)):
t.Fatalf("expected: %s, actual: %s", exp, out)
}
})

t.Run("json", func(t *testing.T) {
t.Parallel()

const exp = `{"example":{"test1":1,"test2":2}}`

got, err := json.Marshal(v)
switch {
case err != nil:
t.Fatalf("expect no marshal error, got: %s", err)
case exp != string(got):
t.Fatalf("expected: %s, actual: %s", exp, got)
}
})
}

0 comments on commit 22b0d67

Please sign in to comment.