diff --git a/README.md b/README.md
index 84239d117..065c93a76 100644
--- a/README.md
+++ b/README.md
@@ -99,6 +99,7 @@ OPTIONS:
--codeExampleFiles value, --cef value Parse folder containing code example files to use for the x-codeSamples extension, disabled by default
--parseInternal Parse go files in internal packages, disabled by default (default: false)
--generatedTime Generate timestamp at the top of docs.go, disabled by default (default: false)
+ --requiredByDefault Set validation required for all fields by default (default: false)
--parseDepth value Dependency parse depth (default: 100)
--instanceName value This parameter can be used to name different swagger document instances. It is optional.
--overridesFile value File to read global type overrides from. (default: ".swaggo")
@@ -488,7 +489,7 @@ type Foo struct {
Field Name | Type | Description
---|:---:|---
-validate | `string` | Determines the validation for the parameter. Possible values are: `required`.
+validate | `string` | Determines the validation for the parameter. Possible values are: `required,optional`.
default | * | Declares the value of the parameter that the server will use if none is provided, for example a "count" to control the number of results per page might default to 100 if not supplied by the client in the request. (Note: "default" has no meaning for required parameters.) See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. Unlike JSON Schema this value MUST conform to the defined [`type`](#parameterType) for this parameter.
maximum | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.2.
minimum | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.3.
diff --git a/cmd/swag/main.go b/cmd/swag/main.go
index 0c689f626..b6805c786 100644
--- a/cmd/swag/main.go
+++ b/cmd/swag/main.go
@@ -15,23 +15,24 @@ import (
)
const (
- searchDirFlag = "dir"
- excludeFlag = "exclude"
- generalInfoFlag = "generalInfo"
- propertyStrategyFlag = "propertyStrategy"
- outputFlag = "output"
- outputTypesFlag = "outputTypes"
- parseVendorFlag = "parseVendor"
- parseDependencyFlag = "parseDependency"
- markdownFilesFlag = "markdownFiles"
- codeExampleFilesFlag = "codeExampleFiles"
- parseInternalFlag = "parseInternal"
- generatedTimeFlag = "generatedTime"
- parseDepthFlag = "parseDepth"
- instanceNameFlag = "instanceName"
- overridesFileFlag = "overridesFile"
- parseGoListFlag = "parseGoList"
- quietFlag = "quiet"
+ searchDirFlag = "dir"
+ excludeFlag = "exclude"
+ generalInfoFlag = "generalInfo"
+ propertyStrategyFlag = "propertyStrategy"
+ outputFlag = "output"
+ outputTypesFlag = "outputTypes"
+ parseVendorFlag = "parseVendor"
+ parseDependencyFlag = "parseDependency"
+ markdownFilesFlag = "markdownFiles"
+ codeExampleFilesFlag = "codeExampleFiles"
+ parseInternalFlag = "parseInternal"
+ generatedTimeFlag = "generatedTime"
+ requiredByDefaultFlag = "requiredByDefault"
+ parseDepthFlag = "parseDepth"
+ instanceNameFlag = "instanceName"
+ overridesFileFlag = "overridesFile"
+ parseGoListFlag = "parseGoList"
+ quietFlag = "quiet"
)
var initFlags = []cli.Flag{
@@ -108,6 +109,10 @@ var initFlags = []cli.Flag{
Value: 100,
Usage: "Dependency parse depth",
},
+ &cli.BoolFlag{
+ Name: requiredByDefaultFlag,
+ Usage: "Set validation required for all fields by default",
+ },
&cli.StringFlag{
Name: instanceNameFlag,
Value: "",
@@ -155,6 +160,7 @@ func initAction(ctx *cli.Context) error {
MarkdownFilesDir: ctx.String(markdownFilesFlag),
ParseInternal: ctx.Bool(parseInternalFlag),
GeneratedTime: ctx.Bool(generatedTimeFlag),
+ RequiredByDefault: ctx.Bool(requiredByDefaultFlag),
CodeExampleFilesDir: ctx.String(codeExampleFilesFlag),
ParseDepth: ctx.Int(parseDepthFlag),
InstanceName: ctx.String(instanceNameFlag),
diff --git a/field_parser.go b/field_parser.go
index bd4fa4218..ce1ef4bf5 100644
--- a/field_parser.go
+++ b/field_parser.go
@@ -18,6 +18,7 @@ var _ FieldParser = &tagBaseFieldParser{p: nil, field: nil, tag: ""}
const (
requiredLabel = "required"
+ optionalLabel = "optional"
swaggerTypeTag = "swaggertype"
swaggerIgnoreTag = "swaggerignore"
)
@@ -472,8 +473,11 @@ func (ps *tagBaseFieldParser) IsRequired() (bool, error) {
bindingTag := ps.tag.Get(bindingTag)
if bindingTag != "" {
for _, val := range strings.Split(bindingTag, ",") {
- if val == requiredLabel {
+ switch val {
+ case requiredLabel:
return true, nil
+ case optionalLabel:
+ return false, nil
}
}
}
@@ -481,13 +485,16 @@ func (ps *tagBaseFieldParser) IsRequired() (bool, error) {
validateTag := ps.tag.Get(validateTag)
if validateTag != "" {
for _, val := range strings.Split(validateTag, ",") {
- if val == requiredLabel {
+ switch val {
+ case requiredLabel:
return true, nil
+ case optionalLabel:
+ return false, nil
}
}
}
- return false, nil
+ return ps.p.RequiredByDefault, nil
}
func parseValidTags(validTag string, sf *structField) {
diff --git a/field_parser_test.go b/field_parser_test.go
index aa89d6ac8..a7487c03d 100644
--- a/field_parser_test.go
+++ b/field_parser_test.go
@@ -82,6 +82,47 @@ func TestDefaultFieldParser(t *testing.T) {
assert.Equal(t, true, got)
})
+ t.Run("Default required tag", func(t *testing.T) {
+ t.Parallel()
+
+ got, err := newTagBaseFieldParser(
+ &Parser{
+ RequiredByDefault: true,
+ },
+ &ast.Field{Tag: &ast.BasicLit{
+ Value: `json:"test"`,
+ }},
+ ).IsRequired()
+ assert.NoError(t, err)
+ assert.True(t, got)
+ })
+
+ t.Run("Optional tag", func(t *testing.T) {
+ t.Parallel()
+
+ got, err := newTagBaseFieldParser(
+ &Parser{
+ RequiredByDefault: true,
+ },
+ &ast.Field{Tag: &ast.BasicLit{
+ Value: `json:"test" binding:"optional"`,
+ }},
+ ).IsRequired()
+ assert.NoError(t, err)
+ assert.False(t, got)
+
+ got, err = newTagBaseFieldParser(
+ &Parser{
+ RequiredByDefault: true,
+ },
+ &ast.Field{Tag: &ast.BasicLit{
+ Value: `json:"test" validate:"optional"`,
+ }},
+ ).IsRequired()
+ assert.NoError(t, err)
+ assert.False(t, got)
+ })
+
t.Run("Extensions tag", func(t *testing.T) {
t.Parallel()
diff --git a/gen/gen.go b/gen/gen.go
index ecdb9373d..b85290b4f 100644
--- a/gen/gen.go
+++ b/gen/gen.go
@@ -105,6 +105,9 @@ type Config struct {
// GeneratedTime whether swag should generate the timestamp at the top of docs.go
GeneratedTime bool
+ // RequiredByDefault set validation required for all fields by default
+ RequiredByDefault bool
+
// OverridesFile defines global type overrides.
OverridesFile string
@@ -159,6 +162,7 @@ func (g *Gen) Build(config *Config) error {
p.ParseVendor = config.ParseVendor
p.ParseDependency = config.ParseDependency
p.ParseInternal = config.ParseInternal
+ p.RequiredByDefault = config.RequiredByDefault
if err := p.ParseAPIMultiSearchDir(searchDirs, config.MainAPIFile, config.ParseDepth); err != nil {
return err
diff --git a/parser.go b/parser.go
index 815b2f8c6..ae0046579 100644
--- a/parser.go
+++ b/parser.go
@@ -130,6 +130,9 @@ type Parser struct {
// Strict whether swag should error or warn when it detects cases which are most likely user errors
Strict bool
+ // RequiredByDefault set validation required for all fields by default
+ RequiredByDefault bool
+
// structStack stores full names of the structures that were already parsed or are being parsed now
structStack []*TypeSpecDef