From f0fdff46a67e9cd371ac919e675a8aa2561f5662 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 23 Jun 2020 18:02:28 -0400 Subject: [PATCH 1/6] Implement ozzo-validation --- pkg/codegen/codegen.go | 1 + pkg/codegen/operations.go | 1 + pkg/codegen/schema.go | 91 ++++++++++++++++++++++++++ pkg/codegen/templates/param-types.tmpl | 7 ++ pkg/codegen/templates/templates.gen.go | 14 ++++ pkg/codegen/templates/typedef.tmpl | 7 ++ 6 files changed, 121 insertions(+) diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index 9f12de5c42..a1198aa9f6 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -83,6 +83,7 @@ var ( {lookFor: "url\\.", packageName: "net/url"}, {lookFor: "xml\\.", packageName: "encoding/xml"}, {lookFor: "yaml\\.", packageName: "gopkg.in/yaml.v2"}, + {lookFor: "validation\\.", packageName: "github.com/go-ozzo/ozzo-validation/v4"}, } ) diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go index 916643dd37..a09484768e 100644 --- a/pkg/codegen/operations.go +++ b/pkg/codegen/operations.go @@ -598,6 +598,7 @@ func GenerateParamsTypes(op OperationDefinition) []TypeDefinition { } s.GoType = GenStructFromSchema(s) + s.GoValidationCall = GenStructValidationCall(s) td := TypeDefinition{ TypeName: typeName, diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go index c3983d66e1..d70055bead 100644 --- a/pkg/codegen/schema.go +++ b/pkg/codegen/schema.go @@ -2,6 +2,7 @@ package codegen import ( "fmt" + "regexp" "strings" "github.com/getkin/kin-openapi/openapi3" @@ -13,6 +14,9 @@ type Schema struct { GoType string // The Go type needed to represent the schema RefType string // If the type has a type name, this is set + GoValidationCall string + ValidationTag string // validation tags, for using github.com/go-ozzo/ozzo-validation/v4. + EnumValues []string // Enum values Properties []Property // For an object, the fields with names @@ -209,13 +213,23 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { return Schema{}, errors.Wrap(err, "error generating type for additional properties") } outSchema.AdditionalPropertiesType = &additionalSchema + // Validation rules: + if schema.MinProps > 0 || schema.MaxProps != nil { + maxProps := 0 + if schema.MaxItems != nil { + maxProps = int(*schema.MaxProps) + } + outSchema.AdditionalPropertiesType.ValidationTag = fmt.Sprintf("validation.Length(%d, %d)", schema.MinProps, maxProps) + } } outSchema.GoType = GenStructFromSchema(outSchema) + outSchema.GoValidationCall = GenStructValidationCall(outSchema) } return outSchema, nil } else { f := schema.Format + var validations []string switch t { case "array": @@ -227,6 +241,17 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } outSchema.GoType = "[]" + arrayType.TypeDecl() outSchema.Properties = arrayType.Properties + if schema.MinItems > 0 || schema.MaxItems != nil { + maxItems := 0 + if schema.MaxItems != nil { + maxItems = int(*schema.MaxItems) + } + validations = append(validations, fmt.Sprintf("validation.Length(%d, %d)", schema.MinItems, maxItems)) + } + if arrayType.ValidationTag != "" { + validations = append(validations, fmt.Sprintf("validation.Each(%s)", arrayType.ValidationTag)) + } + case "integer": // We default to int if format doesn't ask for something else. if f == "int64" { @@ -238,6 +263,15 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } else { return Schema{}, fmt.Errorf("invalid integer format: %s", f) } + if schema.Min != nil { + validations = append(validations, fmt.Sprintf("validation.Min(%v)", *schema.Min)) + } + if schema.Max != nil { + validations = append(validations, fmt.Sprintf("validation.Max(%v)", *schema.Max)) + } + if schema.MultipleOf != nil { + validations = append(validations, fmt.Sprintf("validation.MultipleOf(%v)", *schema.MultipleOf)) + } case "number": // We default to float for "number" if f == "double" { @@ -247,6 +281,15 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } else { return Schema{}, fmt.Errorf("invalid number format: %s", f) } + if schema.Min != nil { + validations = append(validations, fmt.Sprintf("validation.Min(%v)", *schema.Min)) + } + if schema.Max != nil { + validations = append(validations, fmt.Sprintf("validation.Max(%v)", *schema.Max)) + } + if schema.MultipleOf != nil { + validations = append(validations, fmt.Sprintf("validation.MultipleOf(%v)", *schema.MultipleOf)) + } case "boolean": if f != "" { return Schema{}, fmt.Errorf("invalid format (%s) for boolean", f) @@ -256,6 +299,13 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { for _, enumValue := range schema.Enum { outSchema.EnumValues = append(outSchema.EnumValues, enumValue.(string)) } + if len(schema.Enum) > 0 { + var goValues []string + for _, value := range outSchema.EnumValues { + goValues = append(goValues, fmt.Sprintf("%#v", value)) + } + validations = append(validations, fmt.Sprintf("validation.In(%s)", strings.Join(goValues, ", "))) + } // Special case string formats here. switch f { case "byte": @@ -270,10 +320,25 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { default: // All unrecognized formats are simply a regular string. outSchema.GoType = "string" + if schema.MinLength > 0 || schema.MaxLength != nil { + maxLength := 0 + if schema.MaxLength != nil { + maxLength = int(*schema.MaxLength) + } + validations = append(validations, fmt.Sprintf("validation.Length(%d, %d)", schema.MinLength, maxLength)) + } + if schema.Pattern != "" { + // Try to compile it first + if _, err := regexp.Compile(schema.Pattern); err == nil { + validations = append(validations, fmt.Sprintf("validation.Match(regexp.MustCompile(%#v))", schema.Pattern)) + } + } } default: return Schema{}, fmt.Errorf("unhandled Schema type: %s", t) } + outSchema.ValidationTag = strings.Join(validations, ", ") + outSchema.GoValidationCall = fmt.Sprintf("validation.Validate(s, %s)", strings.Join(append(validations, "validation.Skip"), ", ")) } return outSchema, nil } @@ -335,9 +400,33 @@ func GenStructFromSchema(schema Schema) string { return strings.Join(objectParts, "\n") } +func GenStructValidationCall(schema Schema, embeddedFields ...string) string { + // Start out with the validation struct call + callParts := []string{"validation.ValidateStruct(&s, "} + for _, field := range embeddedFields { + callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s),", field)) + } + // Append all the field validations + for _, prop := range schema.Properties { + var validations []string + if prop.Required { + validations = append(validations, "validation.Required") + } + validations = append(validations, prop.Schema.ValidationTag) + callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s, %s),", prop.GoFieldName(), strings.Join(validations, ", "))) + } + // Close the struct + if schema.HasAdditionalProperties { + callParts = append(callParts, fmt.Sprintf("validation.Field(&s.AdditionalProperties, %s),", schema.AdditionalPropertiesType.ValidationTag)) + } + callParts = append(callParts, ")") + return strings.Join(callParts, "\n") +} + // Merge all the fields in the schemas supplied into one giant schema. func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { var outSchema Schema + var refs []string for _, schemaOrRef := range allOf { ref := schemaOrRef.Ref @@ -348,6 +437,7 @@ func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { if err != nil { return Schema{}, errors.Wrap(err, "error converting reference path to a go type") } + refs = append(refs, refType) } schema, err := GenerateGoSchema(schemaOrRef, path) @@ -382,6 +472,7 @@ func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { // Now, we generate the struct which merges together all the fields. var err error outSchema.GoType, err = GenStructFromAllOf(allOf, path) + outSchema.GoValidationCall = GenStructValidationCall(outSchema, refs...) if err != nil { return Schema{}, errors.Wrap(err, "unable to generate aggregate type for AllOf") } diff --git a/pkg/codegen/templates/param-types.tmpl b/pkg/codegen/templates/param-types.tmpl index b35cce5d7c..4b4211a4dd 100644 --- a/pkg/codegen/templates/param-types.tmpl +++ b/pkg/codegen/templates/param-types.tmpl @@ -2,5 +2,12 @@ {{range .TypeDefinitions}} // {{.TypeName}} defines parameters for {{$opid}}. type {{.TypeName}} {{.Schema.TypeDecl}} + +{{if .Schema.GoValidationCall}} +// Validate performs validation on the current {{.TypeName}}. +func (s {{.TypeName}}) Validate() error { + return {{.Schema.GoValidationCall}} +} +{{end}} {{end}} {{end}} diff --git a/pkg/codegen/templates/templates.gen.go b/pkg/codegen/templates/templates.gen.go index 491eda3272..d0dff3804b 100644 --- a/pkg/codegen/templates/templates.gen.go +++ b/pkg/codegen/templates/templates.gen.go @@ -705,6 +705,13 @@ func GetSwagger() (*openapi3.Swagger, error) { {{range .TypeDefinitions}} // {{.TypeName}} defines parameters for {{$opid}}. type {{.TypeName}} {{.Schema.TypeDecl}} + +{{if .Schema.GoValidationCall}} +// Validate performs validation on the current {{.TypeName}}. +func (s {{.TypeName}}) Validate() error { + return {{.Schema.GoValidationCall}} +} +{{end}} {{end}} {{end}} `, @@ -763,6 +770,13 @@ const ( {{- end }} ) {{- end }} + +{{if .Schema.GoValidationCall}} +// Validate performs validation on the current {{.TypeName}}. +func (s {{.TypeName}}) Validate() error { + return {{.Schema.GoValidationCall}} +} +{{end}} {{end}} `, "wrappers.tmpl": `// ServerInterfaceWrapper converts echo contexts to parameters. diff --git a/pkg/codegen/templates/typedef.tmpl b/pkg/codegen/templates/typedef.tmpl index 4f20b07b5b..c018ebc99f 100644 --- a/pkg/codegen/templates/typedef.tmpl +++ b/pkg/codegen/templates/typedef.tmpl @@ -10,4 +10,11 @@ const ( {{- end }} ) {{- end }} + +{{if .Schema.GoValidationCall}} +// Validate performs validation on the current {{.TypeName}}. +func (s {{.TypeName}}) Validate() error { + return {{.Schema.GoValidationCall}} +} +{{end}} {{end}} From 09420c83d48334197a3da50ba8f5161109d43a75 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 25 Jun 2020 19:34:28 -0400 Subject: [PATCH 2/6] Just validations for now... --- pkg/codegen/codegen.go | 1 + pkg/codegen/operations.go | 1 - pkg/codegen/schema.go | 147 +++++++++++-------------- pkg/codegen/templates/param-types.tmpl | 7 -- pkg/codegen/templates/templates.gen.go | 14 --- pkg/codegen/templates/typedef.tmpl | 7 -- 6 files changed, 68 insertions(+), 109 deletions(-) diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index a1198aa9f6..388812ad46 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -84,6 +84,7 @@ var ( {lookFor: "xml\\.", packageName: "encoding/xml"}, {lookFor: "yaml\\.", packageName: "gopkg.in/yaml.v2"}, {lookFor: "validation\\.", packageName: "github.com/go-ozzo/ozzo-validation/v4"}, + {lookFor: "regexp\\.", packageName: "regexp"}, } ) diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go index a09484768e..916643dd37 100644 --- a/pkg/codegen/operations.go +++ b/pkg/codegen/operations.go @@ -598,7 +598,6 @@ func GenerateParamsTypes(op OperationDefinition) []TypeDefinition { } s.GoType = GenStructFromSchema(s) - s.GoValidationCall = GenStructValidationCall(s) td := TypeDefinition{ TypeName: typeName, diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go index d70055bead..5c3760f315 100644 --- a/pkg/codegen/schema.go +++ b/pkg/codegen/schema.go @@ -14,11 +14,13 @@ type Schema struct { GoType string // The Go type needed to represent the schema RefType string // If the type has a type name, this is set - GoValidationCall string - ValidationTag string // validation tags, for using github.com/go-ozzo/ozzo-validation/v4. + Validations Validations EnumValues []string // Enum values + ItemType *Schema // For an array, the item's schema. + + EmbeddedFields []string // For an allOf struct Properties []Property // For an object, the fields with names HasAdditionalProperties bool // Whether we support additional properties AdditionalPropertiesType *Schema // And if we do, their type @@ -27,6 +29,30 @@ type Schema struct { SkipOptionalPointer bool // Some types don't need a * in front when they're optional } +// Validations describes validations for a schema. +type Validations struct { + // String + MinLength uint64 + MaxLength *uint64 + Pattern string + Values []string + + // Number + Min *float64 + ExclusiveMin bool + Max *float64 + ExclusiveMax bool + MultipleOf *float64 + + // Array + MinItems uint64 + MaxItems *uint64 + + // Additional Properties + MinProps uint64 + MaxProps *uint64 +} + func (s Schema) IsRef() bool { return s.RefType != "" } @@ -214,22 +240,15 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } outSchema.AdditionalPropertiesType = &additionalSchema // Validation rules: - if schema.MinProps > 0 || schema.MaxProps != nil { - maxProps := 0 - if schema.MaxItems != nil { - maxProps = int(*schema.MaxProps) - } - outSchema.AdditionalPropertiesType.ValidationTag = fmt.Sprintf("validation.Length(%d, %d)", schema.MinProps, maxProps) - } + outSchema.Validations.MinProps = schema.MinProps + outSchema.Validations.MaxProps = schema.MaxProps } outSchema.GoType = GenStructFromSchema(outSchema) - outSchema.GoValidationCall = GenStructValidationCall(outSchema) } return outSchema, nil } else { f := schema.Format - var validations []string switch t { case "array": @@ -241,17 +260,9 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } outSchema.GoType = "[]" + arrayType.TypeDecl() outSchema.Properties = arrayType.Properties - if schema.MinItems > 0 || schema.MaxItems != nil { - maxItems := 0 - if schema.MaxItems != nil { - maxItems = int(*schema.MaxItems) - } - validations = append(validations, fmt.Sprintf("validation.Length(%d, %d)", schema.MinItems, maxItems)) - } - if arrayType.ValidationTag != "" { - validations = append(validations, fmt.Sprintf("validation.Each(%s)", arrayType.ValidationTag)) - } - + outSchema.Validations.MinItems = schema.MinItems + outSchema.Validations.MaxItems = schema.MaxItems + outSchema.ItemType = &arrayType case "integer": // We default to int if format doesn't ask for something else. if f == "int64" { @@ -263,15 +274,11 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } else { return Schema{}, fmt.Errorf("invalid integer format: %s", f) } - if schema.Min != nil { - validations = append(validations, fmt.Sprintf("validation.Min(%v)", *schema.Min)) - } - if schema.Max != nil { - validations = append(validations, fmt.Sprintf("validation.Max(%v)", *schema.Max)) - } - if schema.MultipleOf != nil { - validations = append(validations, fmt.Sprintf("validation.MultipleOf(%v)", *schema.MultipleOf)) - } + outSchema.Validations.Min = schema.Min + outSchema.Validations.ExclusiveMin = schema.ExclusiveMin + outSchema.Validations.Max = schema.Max + outSchema.Validations.ExclusiveMax = schema.ExclusiveMax + outSchema.Validations.MultipleOf = schema.MultipleOf case "number": // We default to float for "number" if f == "double" { @@ -281,15 +288,8 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } else { return Schema{}, fmt.Errorf("invalid number format: %s", f) } - if schema.Min != nil { - validations = append(validations, fmt.Sprintf("validation.Min(%v)", *schema.Min)) - } - if schema.Max != nil { - validations = append(validations, fmt.Sprintf("validation.Max(%v)", *schema.Max)) - } - if schema.MultipleOf != nil { - validations = append(validations, fmt.Sprintf("validation.MultipleOf(%v)", *schema.MultipleOf)) - } + outSchema.Validations.Min = schema.Min + outSchema.Validations.Max = schema.Max case "boolean": if f != "" { return Schema{}, fmt.Errorf("invalid format (%s) for boolean", f) @@ -300,11 +300,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { outSchema.EnumValues = append(outSchema.EnumValues, enumValue.(string)) } if len(schema.Enum) > 0 { - var goValues []string - for _, value := range outSchema.EnumValues { - goValues = append(goValues, fmt.Sprintf("%#v", value)) - } - validations = append(validations, fmt.Sprintf("validation.In(%s)", strings.Join(goValues, ", "))) + outSchema.Validations.Values = outSchema.EnumValues } // Special case string formats here. switch f { @@ -320,25 +316,18 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { default: // All unrecognized formats are simply a regular string. outSchema.GoType = "string" - if schema.MinLength > 0 || schema.MaxLength != nil { - maxLength := 0 - if schema.MaxLength != nil { - maxLength = int(*schema.MaxLength) - } - validations = append(validations, fmt.Sprintf("validation.Length(%d, %d)", schema.MinLength, maxLength)) - } + outSchema.Validations.MinLength = schema.MinLength + outSchema.Validations.MaxLength = schema.MaxLength if schema.Pattern != "" { // Try to compile it first if _, err := regexp.Compile(schema.Pattern); err == nil { - validations = append(validations, fmt.Sprintf("validation.Match(regexp.MustCompile(%#v))", schema.Pattern)) + outSchema.Validations.Pattern = schema.Pattern } } } default: return Schema{}, fmt.Errorf("unhandled Schema type: %s", t) } - outSchema.ValidationTag = strings.Join(validations, ", ") - outSchema.GoValidationCall = fmt.Sprintf("validation.Validate(s, %s)", strings.Join(append(validations, "validation.Skip"), ", ")) } return outSchema, nil } @@ -400,33 +389,32 @@ func GenStructFromSchema(schema Schema) string { return strings.Join(objectParts, "\n") } -func GenStructValidationCall(schema Schema, embeddedFields ...string) string { - // Start out with the validation struct call - callParts := []string{"validation.ValidateStruct(&s, "} - for _, field := range embeddedFields { - callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s),", field)) - } - // Append all the field validations - for _, prop := range schema.Properties { - var validations []string - if prop.Required { - validations = append(validations, "validation.Required") - } - validations = append(validations, prop.Schema.ValidationTag) - callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s, %s),", prop.GoFieldName(), strings.Join(validations, ", "))) - } - // Close the struct - if schema.HasAdditionalProperties { - callParts = append(callParts, fmt.Sprintf("validation.Field(&s.AdditionalProperties, %s),", schema.AdditionalPropertiesType.ValidationTag)) - } - callParts = append(callParts, ")") - return strings.Join(callParts, "\n") -} +// func GenStructValidationCall(schema Schema, embeddedFields ...string) string { +// // Start out with the validation struct call +// callParts := []string{"validation.ValidateStruct(&s, "} +// for _, field := range embeddedFields { +// callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s),", field)) +// } +// // Append all the field validations +// for _, prop := range schema.Properties { +// var validations []string +// if prop.Required { +// validations = append(validations, "validation.Required") +// } +// validations = append(validations, prop.Schema.ValidationTag) +// callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s, %s),", prop.GoFieldName(), strings.Join(validations, ", "))) +// } +// // Close the struct +// if schema.HasAdditionalProperties { +// callParts = append(callParts, fmt.Sprintf("validation.Field(&s.AdditionalProperties, %s),", schema.AdditionalPropertiesType.ValidationTag)) +// } +// callParts = append(callParts, ")") +// return strings.Join(callParts, "\n") +// } // Merge all the fields in the schemas supplied into one giant schema. func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { var outSchema Schema - var refs []string for _, schemaOrRef := range allOf { ref := schemaOrRef.Ref @@ -437,7 +425,7 @@ func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { if err != nil { return Schema{}, errors.Wrap(err, "error converting reference path to a go type") } - refs = append(refs, refType) + outSchema.EmbeddedFields = append(outSchema.EmbeddedFields, refType) } schema, err := GenerateGoSchema(schemaOrRef, path) @@ -472,7 +460,6 @@ func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { // Now, we generate the struct which merges together all the fields. var err error outSchema.GoType, err = GenStructFromAllOf(allOf, path) - outSchema.GoValidationCall = GenStructValidationCall(outSchema, refs...) if err != nil { return Schema{}, errors.Wrap(err, "unable to generate aggregate type for AllOf") } diff --git a/pkg/codegen/templates/param-types.tmpl b/pkg/codegen/templates/param-types.tmpl index 4b4211a4dd..b35cce5d7c 100644 --- a/pkg/codegen/templates/param-types.tmpl +++ b/pkg/codegen/templates/param-types.tmpl @@ -2,12 +2,5 @@ {{range .TypeDefinitions}} // {{.TypeName}} defines parameters for {{$opid}}. type {{.TypeName}} {{.Schema.TypeDecl}} - -{{if .Schema.GoValidationCall}} -// Validate performs validation on the current {{.TypeName}}. -func (s {{.TypeName}}) Validate() error { - return {{.Schema.GoValidationCall}} -} -{{end}} {{end}} {{end}} diff --git a/pkg/codegen/templates/templates.gen.go b/pkg/codegen/templates/templates.gen.go index d0dff3804b..491eda3272 100644 --- a/pkg/codegen/templates/templates.gen.go +++ b/pkg/codegen/templates/templates.gen.go @@ -705,13 +705,6 @@ func GetSwagger() (*openapi3.Swagger, error) { {{range .TypeDefinitions}} // {{.TypeName}} defines parameters for {{$opid}}. type {{.TypeName}} {{.Schema.TypeDecl}} - -{{if .Schema.GoValidationCall}} -// Validate performs validation on the current {{.TypeName}}. -func (s {{.TypeName}}) Validate() error { - return {{.Schema.GoValidationCall}} -} -{{end}} {{end}} {{end}} `, @@ -770,13 +763,6 @@ const ( {{- end }} ) {{- end }} - -{{if .Schema.GoValidationCall}} -// Validate performs validation on the current {{.TypeName}}. -func (s {{.TypeName}}) Validate() error { - return {{.Schema.GoValidationCall}} -} -{{end}} {{end}} `, "wrappers.tmpl": `// ServerInterfaceWrapper converts echo contexts to parameters. diff --git a/pkg/codegen/templates/typedef.tmpl b/pkg/codegen/templates/typedef.tmpl index c018ebc99f..4f20b07b5b 100644 --- a/pkg/codegen/templates/typedef.tmpl +++ b/pkg/codegen/templates/typedef.tmpl @@ -10,11 +10,4 @@ const ( {{- end }} ) {{- end }} - -{{if .Schema.GoValidationCall}} -// Validate performs validation on the current {{.TypeName}}. -func (s {{.TypeName}}) Validate() error { - return {{.Schema.GoValidationCall}} -} -{{end}} {{end}} From f082bd4820677b423a019cdf2a3cbefbf9fb0ca1 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Fri, 7 Aug 2020 16:30:20 -0400 Subject: [PATCH 3/6] Add statusText --- pkg/codegen/template_helpers.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/codegen/template_helpers.go b/pkg/codegen/template_helpers.go index adf72305c4..e98a0c75ba 100644 --- a/pkg/codegen/template_helpers.go +++ b/pkg/codegen/template_helpers.go @@ -16,7 +16,9 @@ package codegen import ( "bytes" "fmt" + "net/http" "os" + "strconv" "strings" "text/template" @@ -277,4 +279,11 @@ var TemplateFunctions = template.FuncMap{ "lower": strings.ToLower, "title": strings.Title, "stripNewLines": stripNewLines, + "statusText": func(s string) (string, error) { + v, err := strconv.Atoi(s) + if err != nil { + return "", err + } + return http.StatusText(v), nil + }, } From 0e9d2369f80ec614b7830fdf0c04271f86a3796b Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 11 Aug 2020 15:50:38 -0400 Subject: [PATCH 4/6] Differentiate externally defined types --- pkg/codegen/schema.go | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go index e49a2eeaa2..f585b32f97 100644 --- a/pkg/codegen/schema.go +++ b/pkg/codegen/schema.go @@ -14,6 +14,7 @@ type Schema struct { GoType string // The Go type needed to represent the schema RefType string // If the type has a type name, this is set + IsExternal bool // Whether it was defined externally, i.e. "x-go-type" Validations Validations EnumValues map[string]string // Enum values @@ -142,6 +143,20 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { }, nil } + outSchema := Schema{ + RefType: refType, + } + // Check for custom Go type extension + if extension, ok := schema.Extensions[extPropGoType]; ok { + typeName, err := extTypeName(extension) + if err != nil { + return outSchema, errors.Wrapf(err, "invalid value for %q", extPropGoType) + } + outSchema.GoType = typeName + outSchema.IsExternal = true + return outSchema, nil + } + // We can't support this in any meaningful way if schema.AnyOf != nil { return Schema{GoType: "interface{}", RefType: refType}, nil @@ -164,20 +179,6 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { return mergedSchema, nil } - outSchema := Schema{ - RefType: refType, - } - - // Check for custom Go type extension - if extension, ok := schema.Extensions[extPropGoType]; ok { - typeName, err := extTypeName(extension) - if err != nil { - return outSchema, errors.Wrapf(err, "invalid value for %q", extPropGoType) - } - outSchema.GoType = typeName - return outSchema, nil - } - // Schema type and format, eg. string / binary t := schema.Type // Handle objects and empty schemas first as a special case From 9208c562fec74a0e9f6ff378f2c63fdb55eaa611 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Wed, 26 Aug 2020 13:20:26 -0400 Subject: [PATCH 5/6] Sort validation values --- pkg/codegen/schema.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go index f585b32f97..b8c014c86b 100644 --- a/pkg/codegen/schema.go +++ b/pkg/codegen/schema.go @@ -3,6 +3,7 @@ package codegen import ( "fmt" "regexp" + "sort" "strings" "github.com/getkin/kin-openapi/openapi3" @@ -317,6 +318,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { for _, value := range outSchema.EnumValues { outSchema.Validations.Values = append(outSchema.Validations.Values, value) } + sort.Sort(sort.StringSlice(outSchema.Validations.Values)) } // Special case string formats here. From 7fff5f6294715797098c61d5d2a4e6c05113b5fc Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Wed, 26 Aug 2020 13:28:44 -0400 Subject: [PATCH 6/6] Clean up unneeded parts --- pkg/codegen/codegen.go | 2 -- pkg/codegen/schema.go | 23 ----------------------- pkg/codegen/template_helpers.go | 9 --------- 3 files changed, 34 deletions(-) diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index ae04a18bbf..7dc51012a8 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -85,8 +85,6 @@ var ( {lookFor: "url\\.", packageName: "net/url"}, {lookFor: "xml\\.", packageName: "encoding/xml"}, {lookFor: "yaml\\.", packageName: "gopkg.in/yaml.v2"}, - {lookFor: "validation\\.", packageName: "github.com/go-ozzo/ozzo-validation/v4"}, - {lookFor: "regexp\\.", packageName: "regexp"}, } importMapping = map[string]goImport{} diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go index b8c014c86b..dbe6657aed 100644 --- a/pkg/codegen/schema.go +++ b/pkg/codegen/schema.go @@ -410,29 +410,6 @@ func GenStructFromSchema(schema Schema) string { return strings.Join(objectParts, "\n") } -// func GenStructValidationCall(schema Schema, embeddedFields ...string) string { -// // Start out with the validation struct call -// callParts := []string{"validation.ValidateStruct(&s, "} -// for _, field := range embeddedFields { -// callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s),", field)) -// } -// // Append all the field validations -// for _, prop := range schema.Properties { -// var validations []string -// if prop.Required { -// validations = append(validations, "validation.Required") -// } -// validations = append(validations, prop.Schema.ValidationTag) -// callParts = append(callParts, fmt.Sprintf("validation.Field(&s.%s, %s),", prop.GoFieldName(), strings.Join(validations, ", "))) -// } -// // Close the struct -// if schema.HasAdditionalProperties { -// callParts = append(callParts, fmt.Sprintf("validation.Field(&s.AdditionalProperties, %s),", schema.AdditionalPropertiesType.ValidationTag)) -// } -// callParts = append(callParts, ")") -// return strings.Join(callParts, "\n") -// } - // Merge all the fields in the schemas supplied into one giant schema. func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { var outSchema Schema diff --git a/pkg/codegen/template_helpers.go b/pkg/codegen/template_helpers.go index e98a0c75ba..adf72305c4 100644 --- a/pkg/codegen/template_helpers.go +++ b/pkg/codegen/template_helpers.go @@ -16,9 +16,7 @@ package codegen import ( "bytes" "fmt" - "net/http" "os" - "strconv" "strings" "text/template" @@ -279,11 +277,4 @@ var TemplateFunctions = template.FuncMap{ "lower": strings.ToLower, "title": strings.Title, "stripNewLines": stripNewLines, - "statusText": func(s string) (string, error) { - v, err := strconv.Atoi(s) - if err != nil { - return "", err - } - return http.StatusText(v), nil - }, }