mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-14 02:10:00 +08:00
fix(swagger): add example field to path/form/header parameters (#5497)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
34
tools/goctl/api/swagger/issue5496/issue5496.api
Normal file
34
tools/goctl/api/swagger/issue5496/issue5496.api
Normal file
@@ -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)
|
||||||
|
}
|
||||||
81
tools/goctl/api/swagger/issue5496/issue5496.json
Normal file
81
tools/goctl/api/swagger/issue5496/issue5496.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
@@ -72,6 +72,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
SimpleSchema: spec.SimpleSchema{
|
SimpleSchema: spec.SimpleSchema{
|
||||||
Type: sampleTypeFromGoType(ctx, member.Type),
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
||||||
Default: defValueFromOptions(ctx, headerTag.Options, member.Type),
|
Default: defValueFromOptions(ctx, headerTag.Options, member.Type),
|
||||||
|
Example: exampleValueFromOptions(ctx, headerTag.Options, member.Type),
|
||||||
Items: sampleItemsFromGoType(ctx, member.Type),
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
||||||
},
|
},
|
||||||
ParamProps: spec.ParamProps{
|
ParamProps: spec.ParamProps{
|
||||||
@@ -96,6 +97,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
SimpleSchema: spec.SimpleSchema{
|
SimpleSchema: spec.SimpleSchema{
|
||||||
Type: sampleTypeFromGoType(ctx, member.Type),
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
||||||
Default: defValueFromOptions(ctx, pathParameterTag.Options, member.Type),
|
Default: defValueFromOptions(ctx, pathParameterTag.Options, member.Type),
|
||||||
|
Example: exampleValueFromOptions(ctx, pathParameterTag.Options, member.Type),
|
||||||
Items: sampleItemsFromGoType(ctx, member.Type),
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
||||||
},
|
},
|
||||||
ParamProps: spec.ParamProps{
|
ParamProps: spec.ParamProps{
|
||||||
@@ -121,6 +123,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
SimpleSchema: spec.SimpleSchema{
|
SimpleSchema: spec.SimpleSchema{
|
||||||
Type: sampleTypeFromGoType(ctx, member.Type),
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
||||||
Default: defValueFromOptions(ctx, formTag.Options, member.Type),
|
Default: defValueFromOptions(ctx, formTag.Options, member.Type),
|
||||||
|
Example: exampleValueFromOptions(ctx, formTag.Options, member.Type),
|
||||||
Items: sampleItemsFromGoType(ctx, member.Type),
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
||||||
},
|
},
|
||||||
ParamProps: spec.ParamProps{
|
ParamProps: spec.ParamProps{
|
||||||
@@ -143,6 +146,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
SimpleSchema: spec.SimpleSchema{
|
SimpleSchema: spec.SimpleSchema{
|
||||||
Type: sampleTypeFromGoType(ctx, member.Type),
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
||||||
Default: defValueFromOptions(ctx, formTag.Options, member.Type),
|
Default: defValueFromOptions(ctx, formTag.Options, member.Type),
|
||||||
|
Example: exampleValueFromOptions(ctx, formTag.Options, member.Type),
|
||||||
Items: sampleItemsFromGoType(ctx, member.Type),
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
||||||
},
|
},
|
||||||
ParamProps: spec.ParamProps{
|
ParamProps: spec.ParamProps{
|
||||||
|
|||||||
@@ -83,6 +83,41 @@ func TestParametersFromType_EdgeCases(t *testing.T) {
|
|||||||
assert.Empty(t, params)
|
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 {
|
func createTestStruct(name string, hasJson bool) apiSpec.DefineStruct {
|
||||||
tag := `form:"username"`
|
tag := `form:"username"`
|
||||||
if hasJson {
|
if hasJson {
|
||||||
|
|||||||
Reference in New Issue
Block a user