Skip to content

Commit

Permalink
Merge pull request #16 from miketonks/allow-nullable-inner-values
Browse files Browse the repository at this point in the history
Allow nullable values in nested objects
  • Loading branch information
benpaxton-hf authored Mar 31, 2022
2 parents 97c1e62 + 69f0885 commit 55565e1
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 29 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.16
require (
github.com/gin-gonic/gin v1.7.4
github.com/labstack/echo/v4 v4.6.1
github.com/miketonks/swag v0.0.0-20211006155010-b4fa61e72278 // indirect
github.com/miketonks/swag v0.0.0-20211006155010-b4fa61e72278
github.com/stretchr/testify v1.7.0
github.com/xeipuuv/gojsonschema v1.2.0
)
58 changes: 33 additions & 25 deletions swag-validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,38 @@ func buildRequestSchema(e *swagger.Endpoint) *RequestSchema {
return &r
}

func convertProperty(p swagger.Property) SchemaProperty {
sp := SchemaProperty{
Description: p.Description,
Enum: p.Enum,
Format: p.Format,
Ref: p.Ref,
Example: p.Example,
Items: p.Items,
Pattern: p.Pattern,
MinItems: p.MinItems,
MaxItems: p.MaxItems,
UniqueItems: p.UniqueItems,
MinLength: p.MinLength,
MaxLength: p.MaxLength,
Minimum: p.Minimum,
Maximum: p.Maximum,
ExclusiveMinimum: p.ExclusiveMinimum,
ExclusiveMaximum: p.ExclusiveMaximum,
AdditionalProperties: p.AdditionalProperties,
}
if p.Type != "" {
sp.Type = strings.Split(p.Type, ",")
}
if p.Nullable {
sp.Type = append(sp.Type, "null")
}
if prop, ok := p.AdditionalProperties.(*swagger.Property); ok {
sp.AdditionalProperties = convertProperty(*prop)
}
return sp
}

func buildSchemaDefinitions(api *swagger.API) map[string]SchemaDefinition {
defs := map[string]SchemaDefinition{}
for _, d := range api.Definitions {
Expand All @@ -592,31 +624,7 @@ func buildSchemaDefinitions(api *swagger.API) map[string]SchemaDefinition {
AdditionalProperties: d.AdditionalProperties,
}
for k, p := range d.Properties {
sp := SchemaProperty{
Description: p.Description,
Enum: p.Enum,
Format: p.Format,
Ref: p.Ref,
Example: p.Example,
Items: p.Items,
Pattern: p.Pattern,
MinItems: p.MinItems,
MaxItems: p.MaxItems,
UniqueItems: p.UniqueItems,
MinLength: p.MinLength,
MaxLength: p.MaxLength,
Minimum: p.Minimum,
Maximum: p.Maximum,
ExclusiveMinimum: p.ExclusiveMinimum,
ExclusiveMaximum: p.ExclusiveMaximum,
AdditionalProperties: p.AdditionalProperties,
}
if p.Type != "" {
sp.Type = strings.Split(p.Type, ",")
}
if p.Nullable {
sp.Type = append(sp.Type, "null")
}
sp := convertProperty(p)

schemaDef.Properties[k] = sp
}
Expand Down
25 changes: 24 additions & 1 deletion swag-validator_echo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func TestPayloadEcho(t *testing.T) {

testTable := []struct {
description string
in payload
in interface{}
expectedStatus int
expectedResponse map[string]interface{}
}{
Expand Down Expand Up @@ -457,6 +457,25 @@ func TestPayloadEcho(t *testing.T) {
expectedStatus: 200,
expectedResponse: nil,
},
{
description: "Non-nullable map has no null elems, nullable has both null and non-null elems",
in: map[string]interface{}{
"non_null_elems": map[string]*string{"foo": pString("bar")},
"nullable_elems": map[string]*string{"foo": pString("bar"), "baz": nil},
},
expectedStatus: 200,
expectedResponse: nil,
},
{
description: "Non-nullable map has null elems",
in: map[string]interface{}{
"non_null_elems": map[string]*string{"foo": nil},
},
expectedStatus: 400,
expectedResponse: map[string]interface{}{
"non_null_elems.foo": "Invalid type. Expected: string, given: null",
},
},
}

api := swag.New(swag.Endpoints(endpoint.New("POST", "/validate-test", "Test the validator",
Expand Down Expand Up @@ -484,6 +503,10 @@ func TestPayloadEcho(t *testing.T) {
}
}

func pString(s string) *string {
return &s
}

func TestOptionsReturnErrorsEcho(t *testing.T) {

api := swag.New(
Expand Down
21 changes: 20 additions & 1 deletion swag-validator_gin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func TestPayloadGin(t *testing.T) {

testTable := []struct {
description string
in payload
in interface{}
expectedStatus int
expectedResponse map[string]interface{}
}{
Expand Down Expand Up @@ -464,6 +464,25 @@ func TestPayloadGin(t *testing.T) {
expectedStatus: 200,
expectedResponse: nil,
},
{
description: "Non-nullable map has no null elems, nullable has both null and non-null elems",
in: map[string]interface{}{
"non_null_elems": map[string]*string{"foo": pString("bar")},
"nullable_elems": map[string]*string{"foo": pString("bar"), "baz": nil},
},
expectedStatus: 200,
expectedResponse: nil,
},
{
description: "Non-nullable map has null elems",
in: map[string]interface{}{
"non_null_elems": map[string]*string{"foo": nil},
},
expectedStatus: 400,
expectedResponse: map[string]interface{}{
"non_null_elems.foo": "Invalid type. Expected: string, given: null",
},
},
}

api := swag.New(swag.Endpoints(endpoint.New("POST", "/validate-test", "Test the validator",
Expand Down
5 changes: 4 additions & 1 deletion swag-validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ type payload struct {
MaxItemsArr []string `json:"max_items_arr,omitempty" max_items:"3"`
MinItemsArr []string `json:"min_items_arr,omitempty" min_items:"2"`
UniqueItemsAarr []string `json:"unique_items_arr,omitempty" unique_items:"true"`

NonNullElems map[string]string `json:"non_null_elems,omitempty"`
NullableElems map[string]*string `json:"nullable_elems,omitempty"`
}

func preparePostRequest(url string, body payload) *http.Request {
func preparePostRequest(url string, body interface{}) *http.Request {
buff, err := json.Marshal(body)
if err != nil {
log.Fatalf("Failed to marshal the body: %s", err)
Expand Down

0 comments on commit 55565e1

Please sign in to comment.