From eb2302b71e9c1388fcd00bf0a5985545b318f1f0 Mon Sep 17 00:00:00 2001 From: kesonan Date: Sat, 21 Mar 2026 23:18:55 +0800 Subject: [PATCH] fix(swagger): add example field to path/form/header parameters (#5497) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../goctl/api/swagger/issue5496/issue5496.api | 34 ++++++++ .../api/swagger/issue5496/issue5496.json | 81 +++++++++++++++++++ tools/goctl/api/swagger/parameter.go | 4 + tools/goctl/api/swagger/parameter_test.go | 35 ++++++++ 4 files changed, 154 insertions(+) create mode 100644 tools/goctl/api/swagger/issue5496/issue5496.api create mode 100644 tools/goctl/api/swagger/issue5496/issue5496.json diff --git a/tools/goctl/api/swagger/issue5496/issue5496.api b/tools/goctl/api/swagger/issue5496/issue5496.api new file mode 100644 index 000000000..ca2f709bf --- /dev/null +++ b/tools/goctl/api/swagger/issue5496/issue5496.api @@ -0,0 +1,34 @@ +syntax = "v1" + +info ( + title: "Issue 5496 Reproduce" + version: "v1" + host: "localhost" +) + +// Reproduces issue #5496: +// The `example` tag option in `path` and `form` tags does not appear in generated swagger JSON. +type ( + Request { + // path param with example — should appear as example in swagger + Name string `path:"name,options=you|me,example=nihao"` + // form param with example and range — should appear as example in swagger + Age int `form:"age,optional,range=[1:200],example=18"` + } + Response { + Name string `json:"name,example=nihao"` + Age int `json:"age,example=18"` + } +) + +@server ( + tags: "issue5496" + summary: "Issue 5496 - example field missing for path/form params" +) +service issue5496 { + @doc ( + description: "Demonstrate that example is missing in path/form swagger params" + ) + @handler getUser + get /user/:name (Request) returns (Response) +} diff --git a/tools/goctl/api/swagger/issue5496/issue5496.json b/tools/goctl/api/swagger/issue5496/issue5496.json new file mode 100644 index 000000000..516bf38b2 --- /dev/null +++ b/tools/goctl/api/swagger/issue5496/issue5496.json @@ -0,0 +1,81 @@ +{ + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "swagger": "2.0", + "info": { + "title": "Issue 5496 Reproduce", + "version": "v1" + }, + "host": "localhost", + "basePath": "/", + "paths": { + "/user/{name}": { + "get": { + "description": "Demonstrate that example is missing in path/form swagger params", + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "tags": [ + "issue5496" + ], + "summary": "getUser", + "operationId": "getUser", + "parameters": [ + { + "enum": [ + "you", + "me" + ], + "type": "string", + "example": "nihao", + "name": "name", + "in": "path", + "required": true + }, + { + "maximum": 200, + "minimum": 1, + "type": "integer", + "example": 18, + "name": "age", + "in": "query", + "allowEmptyValue": true + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "type": "object", + "properties": { + "age": { + "type": "integer", + "example": 18 + }, + "name": { + "type": "string", + "example": "nihao" + } + } + } + } + } + } + } + }, + "x-date": "2026-03-19 22:52:34", + "x-description": "This is a goctl generated swagger file.", + "x-github": "https://github.com/zeromicro/go-zero", + "x-go-zero-doc": "https://go-zero.dev/", + "x-goctl-version": "1.10.0" +} \ No newline at end of file diff --git a/tools/goctl/api/swagger/parameter.go b/tools/goctl/api/swagger/parameter.go index 0530bbcf7..15c72cdaa 100644 --- a/tools/goctl/api/swagger/parameter.go +++ b/tools/goctl/api/swagger/parameter.go @@ -72,6 +72,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, headerTag.Options, member.Type), + Example: exampleValueFromOptions(ctx, headerTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ @@ -96,6 +97,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, pathParameterTag.Options, member.Type), + Example: exampleValueFromOptions(ctx, pathParameterTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ @@ -121,6 +123,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, formTag.Options, member.Type), + Example: exampleValueFromOptions(ctx, formTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ @@ -143,6 +146,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, formTag.Options, member.Type), + Example: exampleValueFromOptions(ctx, formTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ diff --git a/tools/goctl/api/swagger/parameter_test.go b/tools/goctl/api/swagger/parameter_test.go index 92939dd33..a437d6661 100644 --- a/tools/goctl/api/swagger/parameter_test.go +++ b/tools/goctl/api/swagger/parameter_test.go @@ -83,6 +83,41 @@ func TestParametersFromType_EdgeCases(t *testing.T) { assert.Empty(t, params) } +// TestParametersFromType_ExampleField reproduces issue #5496: +// example= in path/form tags was not emitted in the generated swagger JSON. +func TestParametersFromType_ExampleField(t *testing.T) { + ctx := testingContext(t) + + testStruct := apiSpec.DefineStruct{ + RawName: "Request", + Members: []apiSpec.Member{ + { + Name: "Name", + Type: apiSpec.PrimitiveType{RawName: "string"}, + Tag: `path:"name,options=you|me,example=nihao"`, + }, + { + Name: "Age", + Type: apiSpec.PrimitiveType{RawName: "int"}, + Tag: `form:"age,optional,range=[1:200],example=18"`, + }, + }, + } + + params := parametersFromType(ctx, http.MethodGet, testStruct) + assert.Len(t, params, 2) + + // path param should have example + pathParam := params[0] + assert.Equal(t, paramsInPath, pathParam.In) + assert.Equal(t, "nihao", pathParam.SimpleSchema.Example, "path param example should be set") + + // form/query param should have example + queryParam := params[1] + assert.Equal(t, paramsInQuery, queryParam.In) + assert.EqualValues(t, int64(18), queryParam.SimpleSchema.Example, "form param example should be set") +} + func createTestStruct(name string, hasJson bool) apiSpec.DefineStruct { tag := `form:"username"` if hasJson {