├── .github ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ └── Feature_request.md ├── actions │ └── danger │ │ └── Dockerfile ├── main.workflow └── workflows │ ├── ci.yml │ └── docker.yml ├── .gitignore ├── .goreleaser.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── Makefile ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── README_pt.md ├── README_zh-CN.md ├── assets ├── swagger-image.png └── swaggo.png ├── cmd └── swag │ └── main.go ├── const.go ├── doc.go ├── enums.go ├── enums_test.go ├── example ├── basic │ ├── api │ │ └── api.go │ ├── docs │ │ ├── docs.go │ │ └── swagger │ │ │ └── swagger.yaml │ ├── main.go │ └── web │ │ └── handler.go ├── celler │ ├── README.md │ ├── controller │ │ ├── accounts.go │ │ ├── admin.go │ │ ├── bottles.go │ │ ├── controller.go │ │ └── examples.go │ ├── docs │ │ ├── docs.go │ │ └── swagger │ │ │ └── swagger.yaml │ ├── go.mod │ ├── go.sum │ ├── httputil │ │ └── error.go │ ├── main.go │ └── model │ │ ├── account.go │ │ ├── admin.go │ │ ├── bottle.go │ │ └── error.go ├── go-module-support │ ├── docs │ │ ├── docs.go │ │ ├── swagger.json │ │ └── swagger.yaml │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── web │ │ └── handler.go ├── markdown │ ├── admin.md │ ├── api.md │ ├── api │ │ └── api.go │ ├── docs │ │ ├── docs.go │ │ ├── swagger.json │ │ └── swagger.yaml │ ├── go.mod │ ├── go.sum │ └── main.go ├── object-map-example │ ├── controller │ │ ├── api.go │ │ ├── controller.go │ │ └── response.go │ ├── docs │ │ ├── docs.go │ │ ├── swagger.json │ │ └── swagger.yaml │ ├── go.mod │ ├── go.sum │ └── main.go └── override │ ├── .swaggo │ ├── docs │ ├── docs.go │ ├── swagger.json │ └── swagger.yaml │ ├── handler.go │ └── main.go ├── field_parser.go ├── field_parser_test.go ├── format ├── format.go └── format_test.go ├── formatter.go ├── formatter_test.go ├── gen ├── gen.go └── gen_test.go ├── generics.go ├── generics_test.go ├── go.mod ├── go.sum ├── golist.go ├── golist_test.go ├── license ├── operation.go ├── operation_test.go ├── package.go ├── packages.go ├── packages_test.go ├── parser.go ├── parser_test.go ├── schema.go ├── schema_test.go ├── spec.go ├── spec_test.go ├── swagger.go ├── swagger_test.go ├── testdata ├── alias_import │ ├── api │ │ └── api.go │ ├── data │ │ └── applicationresponse.go │ ├── expected.json │ ├── main.go │ └── types │ │ └── application.go ├── alias_nested │ ├── cmd │ │ └── main │ │ │ └── main.go │ ├── expected.json │ └── pkg │ │ ├── bad │ │ └── data.go │ │ └── good │ │ └── data.go ├── alias_type │ ├── api │ │ └── api.go │ ├── data │ │ └── alias.go │ ├── main.go │ └── types │ │ └── alias.go ├── api.md ├── code_examples │ ├── api │ │ └── api1.go │ ├── broken.json │ ├── example.json │ └── main.go ├── composition │ ├── api │ │ └── api.go │ ├── common │ │ └── response.go │ ├── expected.json │ └── main.go ├── conflict_name │ ├── api │ │ ├── api1.go │ │ └── api2.go │ ├── expected.json │ ├── main.go │ ├── model │ │ └── model.go │ └── model2 │ │ └── model.go ├── delims │ ├── api │ │ └── api.go │ ├── expected.json │ └── main.go ├── deprecated_router │ ├── api │ │ └── api.go │ ├── expected.json │ └── main.go ├── deps_having_invalid_pkg │ └── main.go ├── duplicated │ ├── api │ │ └── api.go │ └── main.go ├── duplicated2 │ ├── api │ │ └── api.go │ └── main.go ├── duplicated_function_scoped │ ├── api │ │ └── api.go │ ├── main.go │ └── other_api │ │ └── api.go ├── enums │ ├── api │ │ └── api.go │ ├── consts │ │ └── const.go │ ├── expected.json │ ├── main.go │ └── types │ │ └── model.go ├── error │ ├── api │ │ └── api.go │ ├── errors │ │ └── errors.go │ ├── expected.json │ ├── main.go │ └── web │ │ └── handler.go ├── extensionsFail1.go ├── extensionsFail2.go ├── external_models │ ├── external │ │ └── model.go │ └── main │ │ ├── api │ │ └── api.go │ │ ├── expected.json │ │ └── main.go ├── fixes-432 │ ├── a │ │ └── a.go │ ├── b │ │ └── b.go │ └── cmd │ │ └── main.go ├── format_dst │ ├── api │ │ └── api.go │ ├── main.go │ └── web │ │ └── handler.go ├── format_empty │ └── empty.go ├── format_src │ ├── api │ │ └── api.go │ ├── main.go │ └── web │ │ └── handler.go ├── format_test │ ├── api │ │ └── api.go │ ├── main.go │ └── web │ │ └── handler.go ├── generics_arrays │ ├── api │ │ └── api.go │ ├── expected.json │ ├── main.go │ ├── types │ │ └── post.go │ └── web │ │ └── handler.go ├── generics_basic │ ├── .swaggo │ ├── api │ │ └── api.go │ ├── expected.json │ ├── main.go │ ├── types │ │ ├── post.go │ │ └── string.go │ └── web │ │ └── handler.go ├── generics_function_scoped │ ├── api │ │ └── api.go │ ├── expected.json │ ├── main.go │ └── types │ │ └── response.go ├── generics_multi_level_nesting │ ├── api │ │ └── api.go │ ├── expected.json │ ├── main.go │ └── web │ │ └── handler.go ├── generics_names │ ├── api │ │ ├── api.go │ │ └── api_alias_pkg.go │ ├── expected.json │ ├── main.go │ ├── types │ │ └── post.go │ └── web │ │ └── handler.go ├── generics_nested │ ├── api │ │ └── api.go │ ├── expected.json │ ├── main.go │ ├── types │ │ └── post.go │ └── web │ │ └── handler.go ├── generics_package_alias │ ├── external │ │ ├── external1 │ │ │ └── external.go │ │ ├── external2 │ │ │ └── external.go │ │ ├── external3 │ │ │ └── external.go │ │ └── external4 │ │ │ └── external.go │ └── internal │ │ ├── api │ │ ├── api1.go │ │ ├── api2.go │ │ ├── api3.go │ │ ├── api4.go │ │ ├── api5.go │ │ ├── api6.go │ │ ├── api7.go │ │ └── api8.go │ │ ├── expected.json │ │ ├── main.go │ │ ├── path1 │ │ └── v1 │ │ │ └── product.go │ │ ├── path2 │ │ └── v1 │ │ │ └── product.go │ │ └── path3 │ │ └── v1 │ │ └── product.go ├── generics_property │ ├── api │ │ └── api.go │ ├── expected.json │ ├── main.go │ ├── types │ │ └── post.go │ └── web │ │ └── handler.go ├── global_override │ ├── api │ │ └── api.go │ ├── data │ │ └── applicationresponse.go │ ├── expected.json │ ├── main.go │ ├── othertypes │ │ └── application.go │ └── types │ │ └── application.go ├── global_security │ ├── api │ │ └── api.go │ ├── expected.json │ └── main.go ├── golist │ ├── api │ │ ├── api.go │ │ ├── foo.c │ │ └── foo.h │ └── main.go ├── golist_disablemodule │ ├── api │ │ ├── api.go │ │ ├── foo.c │ │ └── foo.h │ └── main.go ├── golist_invalid │ └── main.go ├── invalid_external_pkg │ ├── invalid │ │ └── normal.go │ └── main.go ├── json_field_string │ └── main.go ├── main.go ├── markdown.go ├── nested │ ├── api │ │ └── api.go │ ├── common │ │ └── data.go │ ├── expected.json │ └── main.go ├── nested2 │ ├── data.go │ └── inner │ │ └── data.go ├── non_exported_json_fields │ └── main.go ├── param_structs │ └── structs.go ├── pare_outside_dependencies │ └── cmd │ │ └── main.go ├── parseExtension │ └── parseExtension.go ├── pet │ ├── main.go │ └── web │ │ └── handler.go ├── quotes │ ├── api.md │ ├── api │ │ └── api.go │ ├── expected.json │ └── main.go ├── simple │ ├── api │ │ └── api.go │ ├── cross │ │ └── test.go │ ├── expected.json │ ├── main.go │ └── web │ │ └── handler.go ├── simple2 │ ├── api │ │ └── api.go │ ├── main.go │ └── web │ │ └── handler.go ├── simple3 │ ├── api │ │ └── api.go │ ├── main.go │ └── web │ │ └── handler.go ├── simple_cgo │ ├── api │ │ └── api.go │ └── main.go ├── single_file_api │ └── main.go ├── state │ ├── admin_expected.json │ ├── api │ │ ├── api.go │ │ └── api_user.go │ ├── main.go │ ├── user_expected.json │ └── web │ │ └── handler.go ├── struct_comment │ ├── api │ │ └── api.go │ ├── main.go │ └── web │ │ └── handler.go ├── tags │ ├── apes.md │ ├── api.md │ ├── cats.md │ └── main.go ├── tags2 │ ├── apes.md │ ├── api.md │ └── main.go ├── tags_nonexistend_tag │ ├── apes.md │ ├── api.md │ └── main.go ├── templated.go └── users.md ├── types.go ├── utils.go ├── utils_test.go └── version.go /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Your swag version** 24 | e.g. 1.4.1 25 | 26 | **Your go version** 27 | e.g. 1.12.0 28 | 29 | **Desktop (please complete the following information):** 30 | - OS: [e.g. iOS] 31 | - Browser: [e.g. chrome, safari] 32 | - Version: [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/actions/danger/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.6 2 | 3 | LABEL "com.github.actions.name"="Danger" 4 | LABEL "com.github.actions.description"="Run Danger" 5 | LABEL "com.github.actions.icon"="alert-triangle" 6 | LABEL "com.github.actions.color"="yellow" 7 | 8 | RUN apt-get update -qq && apt-get install -y build-essential p7zip unzip 9 | 10 | RUN gem install danger -v '>= 5.10.3' 11 | RUN gem install danger-checkstyle_format 12 | 13 | ENTRYPOINT "danger" 14 | CMD "--verbose" 15 | -------------------------------------------------------------------------------- /.github/main.workflow: -------------------------------------------------------------------------------- 1 | workflow "DangerPullRequest" { 2 | on = "pull_request" 3 | resolves = ["Danger"] 4 | } 5 | 6 | action "Danger" { 7 | uses = "pei0804/GithubActions/danger@master" 8 | secrets = ["GITHUB_TOKEN"] 9 | } 10 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ master, v2 ] 6 | pull_request: 7 | branches: [ master, v2 ] 8 | 9 | jobs: 10 | test: 11 | strategy: 12 | matrix: 13 | go: [ '1.19.x', '1.20.x', '1.21.x', '1.22.x' ] 14 | platform: [ubuntu-latest, macos-latest] 15 | runs-on: ${{ matrix.platform }} 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Set up Go 19 | uses: actions/setup-go@v3 20 | with: 21 | go-version: ${{ matrix.go }} 22 | - name: deps 23 | run: make deps 24 | - name: static program analysis 25 | run: make fmt-check vet 26 | - name: build 27 | run: make build 28 | - name: test 29 | run: make test 30 | - name: coverage 31 | run: bash <(curl -s https://codecov.io/bash) 32 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: docker 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | permissions: 9 | contents: read 10 | packages: write 11 | 12 | jobs: 13 | docker-build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v4 18 | 19 | - name: Set up Docker Buildx 20 | id: buildx 21 | uses: docker/setup-buildx-action@v3 22 | 23 | - name: Login to Github Packages 24 | uses: docker/login-action@v3 25 | with: 26 | registry: ghcr.io 27 | username: ${{ github.actor }} 28 | password: ${{ secrets.GITHUB_TOKEN }} 29 | 30 | - name: Docker meta 31 | id: meta 32 | uses: docker/metadata-action@v5 33 | with: 34 | images: ghcr.io/swaggo/swag 35 | 36 | - name: Build image and push to GitHub Container Registry 37 | id: docker_build 38 | uses: docker/build-push-action@v5 39 | with: 40 | context: . 41 | platforms: linux/amd64,linux/arm64 42 | push: true 43 | tags: | 44 | ghcr.io/${{ github.repository }}:latest 45 | ghcr.io/${{ github.repository }}:${{github.ref_name}} 46 | labels: ${{ steps.meta.outputs.labels }} 47 | 48 | - name: Image digest 49 | run: echo ${{ steps.docker_build.outputs.digest }} 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | testdata/simple*/docs 3 | testdata/quotes/docs 4 | testdata/quotes/quotes.so 5 | testdata/delims/docs 6 | testdata/delims/delims.so 7 | example/basic/docs/* 8 | example/celler/docs/* 9 | cover.out 10 | 11 | 12 | # Test binary, build with `go test -c` 13 | *.test 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | .idea 18 | .vscode 19 | 20 | # Etc 21 | .DS_Store 22 | 23 | /swag 24 | /swag.exe 25 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | build: 2 | main: cmd/swag/main.go 3 | goos: 4 | - linux 5 | - darwin 6 | goarch: 7 | - amd64 8 | - arm64 9 | - 386 10 | env: 11 | - CGO_ENABLED=0 12 | 13 | archives: 14 | - id: foo 15 | name_template: >- 16 | {{ .ProjectName }}_ 17 | {{- .Version }}_ 18 | {{- if eq .Os "linux"}}Linux{{ else if eq .Os "darwin"}}Darwin{{ else }}{{ .Os }}{{ end }}_ 19 | {{- if eq .Arch "386" }}i386{{ else if eq .Arch "amd64" }}x86_64{{ else }}{{ .Arch }}{{ end }} 20 | 21 | checksum: 22 | name_template: 'checksums.txt' 23 | snapshot: 24 | name_template: "{{ .Tag }}-next" 25 | changelog: 26 | sort: asc 27 | filters: 28 | exclude: 29 | - '^docs:' 30 | - '^test:' 31 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Fork it 11 | 2. Create your feature branch (`git checkout -b my-new-feature`) 12 | 3. Commit your changes (`git commit -am 'Add some feature'`) 13 | 4. Push to the branch (`git push origin my-new-feature`) 14 | 5. Create new Pull Request 15 | 16 | Please make an issue first if the change is likely to increase. 17 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile References: https://docs.docker.com/engine/reference/builder/ 2 | 3 | # Start from the latest golang base image 4 | FROM --platform=$BUILDPLATFORM golang:1.21-alpine as builder 5 | 6 | # Set the Current Working Directory inside the container 7 | WORKDIR /app 8 | 9 | # Copy go mod and sum files 10 | COPY go.mod go.sum ./ 11 | 12 | # Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed 13 | RUN go mod download 14 | 15 | # Copy the source from the current directory to the Working Directory inside the container 16 | COPY . . 17 | 18 | # Configure go compiler target platform 19 | ARG TARGETOS 20 | ARG TARGETARCH 21 | ENV GOARCH=$TARGETARCH \ 22 | GOOS=$TARGETOS 23 | 24 | # Build the Go app 25 | RUN CGO_ENABLED=0 GOOS=linux go build -v -a -installsuffix cgo -o swag cmd/swag/main.go 26 | 27 | 28 | ######## Start a new stage from scratch ####### 29 | FROM --platform=$TARGETPLATFORM scratch 30 | 31 | WORKDIR /code/ 32 | 33 | # Copy the Pre-built binary file from the previous stage 34 | COPY --from=builder /app/swag /bin/swag 35 | 36 | ENTRYPOINT ["/bin/swag"] 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GOCMD:=$(shell which go) 2 | GOLINT:=$(shell which golint) 3 | GOIMPORT:=$(shell which goimports) 4 | GOFMT:=$(shell which gofmt) 5 | GOBUILD:=$(GOCMD) build 6 | GOINSTALL:=$(GOCMD) install 7 | GOCLEAN:=$(GOCMD) clean 8 | GOTEST:=$(GOCMD) test 9 | GOMODTIDY:=$(GOCMD) mod tidy 10 | GOGET:=$(GOCMD) get 11 | GOLIST:=$(GOCMD) list 12 | GOVET:=$(GOCMD) vet 13 | GOPATH:=$(shell $(GOCMD) env GOPATH) 14 | u := $(if $(update),-u) 15 | 16 | BINARY_NAME:=swag 17 | PACKAGES:=$(shell $(GOLIST) github.com/swaggo/swag github.com/swaggo/swag/cmd/swag github.com/swaggo/swag/gen github.com/swaggo/swag/format) 18 | GOFILES:=$(shell find . -name "*.go" -type f) 19 | 20 | all: test build 21 | 22 | .PHONY: build 23 | build: deps 24 | $(GOBUILD) -o $(BINARY_NAME) ./cmd/swag 25 | 26 | .PHONY: install 27 | install: deps 28 | $(GOINSTALL) ./cmd/swag 29 | 30 | .PHONY: test 31 | test: 32 | echo "mode: count" > coverage.out 33 | for PKG in $(PACKAGES); do \ 34 | $(GOCMD) test -v -covermode=count -coverprofile=profile.out $$PKG > tmp.out; \ 35 | cat tmp.out; \ 36 | if grep -q "^--- FAIL" tmp.out; then \ 37 | rm tmp.out; \ 38 | exit 1; \ 39 | elif grep -q "build failed" tmp.out; then \ 40 | rm tmp.out; \ 41 | exit; \ 42 | fi; \ 43 | if [ -f profile.out ]; then \ 44 | cat profile.out | grep -v "mode:" >> coverage.out; \ 45 | rm profile.out; \ 46 | fi; \ 47 | done 48 | 49 | .PHONY: clean 50 | clean: 51 | $(GOCLEAN) 52 | rm -f $(BINARY_NAME) 53 | 54 | .PHONY: deps 55 | deps: 56 | $(GOMODTIDY) 57 | 58 | .PHONY: vet 59 | vet: deps 60 | $(GOVET) $(PACKAGES) 61 | 62 | .PHONY: fmt 63 | fmt: 64 | $(GOFMT) -s -w $(GOFILES) 65 | 66 | .PHONY: fmt-check 67 | fmt-check: 68 | @diff=$$($(GOFMT) -s -d $(GOFILES)); \ 69 | if [ -n "$$diff" ]; then \ 70 | echo "Please run 'make fmt' and commit the result:"; \ 71 | echo "$${diff}"; \ 72 | exit 1; \ 73 | fi; 74 | 75 | .PHONY: view-covered 76 | view-covered: 77 | $(GOTEST) -coverprofile=cover.out $(TARGET) 78 | $(GOCMD) tool cover -html=cover.out 79 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Describe the PR** 2 | e.g. add cool parser. 3 | 4 | **Relation issue** 5 | e.g. https://github.com/swaggo/swag/pull/118/files 6 | 7 | **Additional context** 8 | Add any other context about the problem here. 9 | -------------------------------------------------------------------------------- /assets/swagger-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swaggo/swag/93e86851e9f22f1f2db57812cf71fc004c02159c/assets/swagger-image.png -------------------------------------------------------------------------------- /assets/swaggo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swaggo/swag/93e86851e9f22f1f2db57812cf71fc004c02159c/assets/swaggo.png -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package swag converts Go annotations to Swagger Documentation 2.0. 3 | See https://github.com/swaggo/swag for more information about swag. 4 | */ 5 | package swag // import "github.com/swaggo/swag" 6 | -------------------------------------------------------------------------------- /enums.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | const ( 4 | enumVarNamesExtension = "x-enum-varnames" 5 | enumCommentsExtension = "x-enum-comments" 6 | enumDescriptionsExtension = "x-enum-descriptions" 7 | ) 8 | 9 | // EnumValue a model to record an enum consts variable 10 | type EnumValue struct { 11 | key string 12 | Value interface{} 13 | Comment string 14 | } 15 | -------------------------------------------------------------------------------- /enums_test.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | import ( 4 | "encoding/json" 5 | "math/bits" 6 | "os" 7 | "path/filepath" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestParseGlobalEnums(t *testing.T) { 14 | searchDir := "testdata/enums" 15 | expected, err := os.ReadFile(filepath.Join(searchDir, "expected.json")) 16 | assert.NoError(t, err) 17 | 18 | p := New() 19 | err = p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth) 20 | assert.NoError(t, err) 21 | b, err := json.MarshalIndent(p.swagger, "", " ") 22 | assert.NoError(t, err) 23 | assert.Equal(t, string(expected), string(b)) 24 | constsPath := "github.com/swaggo/swag/testdata/enums/consts" 25 | assert.Equal(t, bits.UintSize, p.packages.packages[constsPath].ConstTable["uintSize"].Value) 26 | assert.Equal(t, int32(62), p.packages.packages[constsPath].ConstTable["maxBase"].Value) 27 | assert.Equal(t, 8, p.packages.packages[constsPath].ConstTable["shlByLen"].Value) 28 | assert.Equal(t, 255, p.packages.packages[constsPath].ConstTable["hexnum"].Value) 29 | assert.Equal(t, 15, p.packages.packages[constsPath].ConstTable["octnum"].Value) 30 | assert.Equal(t, `aa\nbb\u8888cc`, p.packages.packages[constsPath].ConstTable["nonescapestr"].Value) 31 | assert.Equal(t, "aa\nbb\u8888cc", p.packages.packages[constsPath].ConstTable["escapestr"].Value) 32 | assert.Equal(t, 1_000_000, p.packages.packages[constsPath].ConstTable["underscored"].Value) 33 | assert.Equal(t, 0b10001000, p.packages.packages[constsPath].ConstTable["binaryInteger"].Value) 34 | } 35 | -------------------------------------------------------------------------------- /example/basic/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/swaggo/swag/example/basic/web" 8 | ) 9 | 10 | // GetStringByInt example 11 | // 12 | // @Summary Add a new pet to the store 13 | // @Description get string by ID 14 | // @ID get-string-by-int 15 | // @Accept json 16 | // @Produce json 17 | // @Param some_id path int true "Some ID" 18 | // @Param some_id body web.Pet true "Some ID" 19 | // @Success 200 {string} string "ok" 20 | // @Failure 400 {object} web.APIError "We need ID!!" 21 | // @Failure 404 {object} web.APIError "Can not find ID" 22 | // @Router /testapi/get-string-by-int/{some_id} [get] 23 | func GetStringByInt(w http.ResponseWriter, r *http.Request) { 24 | var pet web.Pet 25 | if err := json.NewDecoder(r.Body).Decode(&pet); err != nil { 26 | // write your code 27 | return 28 | } 29 | 30 | // write your code 31 | } 32 | 33 | // GetStructArrayByString example 34 | // 35 | // @Description get struct array by ID 36 | // @ID get-struct-array-by-string 37 | // @Accept json 38 | // @Produce json 39 | // @Param some_id path string true "Some ID" 40 | // @Param offset query int true "Offset" 41 | // @Param limit query int true "Offset" 42 | // @Success 200 {string} string "ok" 43 | // @Failure 400 {object} web.APIError "We need ID!!" 44 | // @Failure 404 {object} web.APIError "Can not find ID" 45 | // @Router /testapi/get-struct-array-by-string/{some_id} [get] 46 | func GetStructArrayByString(w http.ResponseWriter, r *http.Request) { 47 | // write your code 48 | } 49 | 50 | // Upload example 51 | // 52 | // @Summary Upload file 53 | // @Description Upload file 54 | // @ID file.upload 55 | // @Accept multipart/form-data 56 | // @Produce json 57 | // @Param file formData file true "this is a test file" 58 | // @Success 200 {string} string "ok" 59 | // @Failure 400 {object} web.APIError "We need ID!!" 60 | // @Failure 404 {object} web.APIError "Can not find ID" 61 | // @Router /file/upload [post] 62 | func Upload(w http.ResponseWriter, r *http.Request) { 63 | // write your code 64 | } 65 | 66 | // AnonymousField example 67 | // 68 | // @Summary use Anonymous field 69 | // @Success 200 {object} web.RevValue "ok" 70 | func AnonymousField() { 71 | 72 | } 73 | 74 | // Pet3 example 75 | type Pet3 struct { 76 | ID int `json:"id"` 77 | } 78 | -------------------------------------------------------------------------------- /example/basic/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/example/basic/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | func main() { 25 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 26 | http.HandleFunc("//testapi/get-struct-array-by-string/", api.GetStructArrayByString) 27 | http.HandleFunc("/testapi/upload", api.Upload) 28 | http.ListenAndServe(":8080", nil) 29 | } 30 | -------------------------------------------------------------------------------- /example/basic/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // Pet example 8 | type Pet struct { 9 | ID int `json:"id"` 10 | Category struct { 11 | ID int `json:"id"` 12 | Name string `json:"name"` 13 | } `json:"category"` 14 | Name string `json:"name"` 15 | PhotoUrls []string `json:"photoUrls"` 16 | Tags []Tag `json:"tags"` 17 | Status string `json:"status"` 18 | } 19 | 20 | // Tag example 21 | type Tag struct { 22 | ID int `json:"id"` 23 | Name string `json:"name"` 24 | } 25 | 26 | // Pet2 example 27 | type Pet2 struct { 28 | ID int `json:"id"` 29 | } 30 | 31 | // APIError example 32 | type APIError struct { 33 | ErrorCode int 34 | ErrorMessage string 35 | CreatedAt time.Time 36 | } 37 | 38 | // RevValueBase example 39 | type RevValueBase struct { 40 | Status bool `json:"Status"` 41 | 42 | Err int32 `json:"Err"` 43 | } 44 | 45 | // RevValue example 46 | type RevValue struct { 47 | RevValueBase 48 | 49 | Data int `json:"Data"` 50 | } 51 | -------------------------------------------------------------------------------- /example/celler/README.md: -------------------------------------------------------------------------------- 1 | # Celler example 2 | 3 | Gen doc 4 | 5 | ```console 6 | $ go get -u github.com/swaggo/swag/cmd/swag 7 | $ swag init 8 | ``` 9 | 10 | Run app 11 | 12 | ```console 13 | $ go run main.go 14 | ``` 15 | 16 | [open swagger](http://localhost:8080/swagger/index.html) 17 | 18 | -------------------------------------------------------------------------------- /example/celler/controller/admin.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | "github.com/swaggo/swag/example/celler/httputil" 10 | "github.com/swaggo/swag/example/celler/model" 11 | ) 12 | 13 | // Auth godoc 14 | // 15 | // @Summary Auth admin 16 | // @Description get admin info 17 | // @Tags accounts,admin 18 | // @Accept json 19 | // @Produce json 20 | // @Success 200 {object} model.Admin 21 | // @Failure 400 {object} httputil.HTTPError 22 | // @Failure 401 {object} httputil.HTTPError 23 | // @Failure 404 {object} httputil.HTTPError 24 | // @Failure 500 {object} httputil.HTTPError 25 | // @Security ApiKeyAuth 26 | // @Router /admin/auth [post] 27 | func (c *Controller) Auth(ctx *gin.Context) { 28 | authHeader := ctx.GetHeader("Authorization") 29 | if len(authHeader) == 0 { 30 | httputil.NewError(ctx, http.StatusBadRequest, errors.New("please set Header Authorization")) 31 | return 32 | } 33 | if authHeader != "admin" { 34 | httputil.NewError(ctx, http.StatusUnauthorized, fmt.Errorf("this user isn't authorized to operation key=%s expected=admin", authHeader)) 35 | return 36 | } 37 | admin := model.Admin{ 38 | ID: 1, 39 | Name: "admin", 40 | } 41 | ctx.JSON(http.StatusOK, admin) 42 | } 43 | -------------------------------------------------------------------------------- /example/celler/controller/bottles.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/gin-gonic/gin" 8 | 9 | "github.com/swaggo/swag/example/celler/httputil" 10 | "github.com/swaggo/swag/example/celler/model" 11 | ) 12 | 13 | // ShowBottle godoc 14 | // 15 | // @Summary Show a bottle 16 | // @Description get string by ID 17 | // @ID get-string-by-int 18 | // @Tags bottles 19 | // @Accept json 20 | // @Produce json 21 | // @Param id path int true "Bottle ID" 22 | // @Success 200 {object} model.Bottle 23 | // @Failure 400 {object} httputil.HTTPError 24 | // @Failure 404 {object} httputil.HTTPError 25 | // @Failure 500 {object} httputil.HTTPError 26 | // @Router /bottles/{id} [get] 27 | func (c *Controller) ShowBottle(ctx *gin.Context) { 28 | id := ctx.Param("id") 29 | bid, err := strconv.Atoi(id) 30 | if err != nil { 31 | httputil.NewError(ctx, http.StatusBadRequest, err) 32 | return 33 | } 34 | bottle, err := model.BottleOne(bid) 35 | if err != nil { 36 | httputil.NewError(ctx, http.StatusNotFound, err) 37 | return 38 | } 39 | ctx.JSON(http.StatusOK, bottle) 40 | } 41 | 42 | // ListBottles godoc 43 | // 44 | // @Summary List bottles 45 | // @Description get bottles 46 | // @Tags bottles 47 | // @Accept json 48 | // @Produce json 49 | // @Success 200 {array} model.Bottle 50 | // @Failure 400 {object} httputil.HTTPError 51 | // @Failure 404 {object} httputil.HTTPError 52 | // @Failure 500 {object} httputil.HTTPError 53 | // @Router /bottles [get] 54 | func (c *Controller) ListBottles(ctx *gin.Context) { 55 | bottles, err := model.BottlesAll() 56 | if err != nil { 57 | httputil.NewError(ctx, http.StatusNotFound, err) 58 | return 59 | } 60 | ctx.JSON(http.StatusOK, bottles) 61 | } 62 | -------------------------------------------------------------------------------- /example/celler/controller/controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | // Controller example 4 | type Controller struct { 5 | } 6 | 7 | // NewController example 8 | func NewController() *Controller { 9 | return &Controller{} 10 | } 11 | 12 | // Message example 13 | type Message struct { 14 | Message string `json:"message" example:"message"` 15 | } 16 | -------------------------------------------------------------------------------- /example/celler/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/swaggo/swag/example/celler 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.9.1 7 | github.com/gofrs/uuid v4.2.0+incompatible 8 | github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 9 | github.com/swaggo/gin-swagger v1.4.2 10 | github.com/swaggo/swag v1.8.1 11 | ) 12 | 13 | require ( 14 | github.com/KyleBanks/depth v1.2.1 // indirect 15 | github.com/PuerkitoBio/purell v1.1.1 // indirect 16 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 17 | github.com/bytedance/sonic v1.9.1 // indirect 18 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 19 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect 20 | github.com/gin-contrib/sse v0.1.0 // indirect 21 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 22 | github.com/go-openapi/jsonreference v0.19.6 // indirect 23 | github.com/go-openapi/spec v0.20.4 // indirect 24 | github.com/go-openapi/swag v0.19.15 // indirect 25 | github.com/go-playground/locales v0.14.1 // indirect 26 | github.com/go-playground/universal-translator v0.18.1 // indirect 27 | github.com/go-playground/validator/v10 v10.14.0 // indirect 28 | github.com/goccy/go-json v0.10.2 // indirect 29 | github.com/josharian/intern v1.0.0 // indirect 30 | github.com/json-iterator/go v1.1.12 // indirect 31 | github.com/klauspost/cpuid/v2 v2.2.4 // indirect 32 | github.com/leodido/go-urn v1.2.4 // indirect 33 | github.com/mailru/easyjson v0.7.6 // indirect 34 | github.com/mattn/go-isatty v0.0.19 // indirect 35 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 36 | github.com/modern-go/reflect2 v1.0.2 // indirect 37 | github.com/pelletier/go-toml/v2 v2.0.8 // indirect 38 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 39 | github.com/ugorji/go/codec v1.2.11 // indirect 40 | golang.org/x/arch v0.3.0 // indirect 41 | golang.org/x/crypto v0.31.0 // indirect 42 | golang.org/x/net v0.25.0 // indirect 43 | golang.org/x/sys v0.28.0 // indirect 44 | golang.org/x/text v0.21.0 // indirect 45 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect 46 | google.golang.org/protobuf v1.33.0 // indirect 47 | gopkg.in/yaml.v2 v2.4.0 // indirect 48 | gopkg.in/yaml.v3 v3.0.1 // indirect 49 | ) 50 | -------------------------------------------------------------------------------- /example/celler/httputil/error.go: -------------------------------------------------------------------------------- 1 | package httputil 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // NewError example 6 | func NewError(ctx *gin.Context, status int, err error) { 7 | er := HTTPError{ 8 | Code: status, 9 | Message: err.Error(), 10 | } 11 | ctx.JSON(status, er) 12 | } 13 | 14 | // HTTPError example 15 | type HTTPError struct { 16 | Code int `json:"code" example:"400"` 17 | Message string `json:"message" example:"status bad request"` 18 | } 19 | -------------------------------------------------------------------------------- /example/celler/model/account.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | uuid "github.com/gofrs/uuid" 8 | ) 9 | 10 | // Account example 11 | type Account struct { 12 | ID int `json:"id" example:"1" format:"int64"` 13 | Name string `json:"name" example:"account name"` 14 | UUID uuid.UUID `json:"uuid" example:"550e8400-e29b-41d4-a716-446655440000" format:"uuid"` 15 | } 16 | 17 | // example 18 | var ( 19 | ErrNameInvalid = errors.New("name is empty") 20 | ) 21 | 22 | // AddAccount example 23 | type AddAccount struct { 24 | Name string `json:"name" example:"account name"` 25 | } 26 | 27 | // Validation example 28 | func (a AddAccount) Validation() error { 29 | switch { 30 | case len(a.Name) == 0: 31 | return ErrNameInvalid 32 | default: 33 | return nil 34 | } 35 | } 36 | 37 | // UpdateAccount example 38 | type UpdateAccount struct { 39 | Name string `json:"name" example:"account name"` 40 | } 41 | 42 | // Validation example 43 | func (a UpdateAccount) Validation() error { 44 | switch { 45 | case len(a.Name) == 0: 46 | return ErrNameInvalid 47 | default: 48 | return nil 49 | } 50 | } 51 | 52 | // AccountsAll example 53 | func AccountsAll(q string) ([]Account, error) { 54 | if q == "" { 55 | return accounts, nil 56 | } 57 | as := []Account{} 58 | for k, v := range accounts { 59 | if q == v.Name { 60 | as = append(as, accounts[k]) 61 | } 62 | } 63 | return as, nil 64 | } 65 | 66 | // AccountOne example 67 | func AccountOne(id int) (Account, error) { 68 | for _, v := range accounts { 69 | if id == v.ID { 70 | return v, nil 71 | } 72 | } 73 | return Account{}, ErrNoRow 74 | } 75 | 76 | // Insert example 77 | func (a Account) Insert() (int, error) { 78 | accountMaxID++ 79 | a.ID = accountMaxID 80 | a.Name = fmt.Sprintf("account_%d", accountMaxID) 81 | accounts = append(accounts, a) 82 | return accountMaxID, nil 83 | } 84 | 85 | // Delete example 86 | func Delete(id int) error { 87 | for k, v := range accounts { 88 | if id == v.ID { 89 | accounts = append(accounts[:k], accounts[k+1:]...) 90 | return nil 91 | } 92 | } 93 | return fmt.Errorf("account id=%d is not found", id) 94 | } 95 | 96 | // Update example 97 | func (a Account) Update() error { 98 | for k, v := range accounts { 99 | if a.ID == v.ID { 100 | accounts[k].Name = a.Name 101 | return nil 102 | } 103 | } 104 | return fmt.Errorf("account id=%d is not found", a.ID) 105 | } 106 | 107 | var accountMaxID = 3 108 | var accounts = []Account{ 109 | {ID: 1, Name: "account_1"}, 110 | {ID: 2, Name: "account_2"}, 111 | {ID: 3, Name: "account_3"}, 112 | } 113 | -------------------------------------------------------------------------------- /example/celler/model/admin.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // Admin example 4 | type Admin struct { 5 | ID int `json:"id" example:"1"` 6 | Name string `json:"name" example:"admin name"` 7 | } 8 | -------------------------------------------------------------------------------- /example/celler/model/bottle.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // Bottle example 4 | type Bottle struct { 5 | ID int `json:"id" example:"1"` 6 | Name string `json:"name" example:"bottle_name"` 7 | Account Account `json:"account"` 8 | } 9 | 10 | // BottlesAll example 11 | func BottlesAll() ([]Bottle, error) { 12 | return bottles, nil 13 | } 14 | 15 | // BottleOne example 16 | func BottleOne(id int) (*Bottle, error) { 17 | for _, v := range bottles { 18 | if id == v.ID { 19 | return &v, nil 20 | } 21 | } 22 | return nil, ErrNoRow 23 | } 24 | 25 | var bottles = []Bottle{ 26 | {ID: 1, Name: "bottle_1", Account: Account{ID: 1, Name: "accout_1"}}, 27 | {ID: 2, Name: "bottle_2", Account: Account{ID: 2, Name: "accout_2"}}, 28 | {ID: 3, Name: "bottle_3", Account: Account{ID: 3, Name: "accout_3"}}, 29 | } 30 | -------------------------------------------------------------------------------- /example/celler/model/error.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import "errors" 4 | 5 | var ( 6 | // ErrNoRow example 7 | ErrNoRow = errors.New("no rows in result set") 8 | ) 9 | -------------------------------------------------------------------------------- /example/go-module-support/docs/docs.go: -------------------------------------------------------------------------------- 1 | // Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT 2 | // This file was generated by swaggo/swag 3 | package docs 4 | 5 | import "github.com/swaggo/swag" 6 | 7 | const docTemplate = `{ 8 | "schemes": {{ marshal .Schemes }}, 9 | "swagger": "2.0", 10 | "info": { 11 | "description": "{{escape .Description}}", 12 | "title": "{{.Title}}", 13 | "termsOfService": "http://swagger.io/terms/", 14 | "contact": { 15 | "name": "API Support", 16 | "url": "http://www.swagger.io/support", 17 | "email": "support@swagger.io" 18 | }, 19 | "license": { 20 | "name": "Apache 2.0", 21 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 22 | }, 23 | "version": "{{.Version}}" 24 | }, 25 | "host": "{{.Host}}", 26 | "basePath": "{{.BasePath}}", 27 | "paths": {} 28 | }` 29 | 30 | // SwaggerInfo holds exported Swagger Info so clients can modify it 31 | var SwaggerInfo = &swag.Spec{ 32 | Version: "1.0", 33 | Host: "petstore.swagger.io", 34 | BasePath: "/v2", 35 | Schemes: []string{}, 36 | Title: "Swagger Example API", 37 | Description: "This is a sample server Petstore server.", 38 | InfoInstanceName: "swagger", 39 | SwaggerTemplate: docTemplate, 40 | } 41 | 42 | func init() { 43 | swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) 44 | } 45 | -------------------------------------------------------------------------------- /example/go-module-support/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server Petstore server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "host": "petstore.swagger.io", 19 | "basePath": "/v2", 20 | "paths": {} 21 | } -------------------------------------------------------------------------------- /example/go-module-support/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: /v2 2 | host: petstore.swagger.io 3 | info: 4 | contact: 5 | email: support@swagger.io 6 | name: API Support 7 | url: http://www.swagger.io/support 8 | description: This is a sample server Petstore server. 9 | license: 10 | name: Apache 2.0 11 | url: http://www.apache.org/licenses/LICENSE-2.0.html 12 | termsOfService: http://swagger.io/terms/ 13 | title: Swagger Example API 14 | version: "1.0" 15 | paths: {} 16 | swagger: "2.0" 17 | -------------------------------------------------------------------------------- /example/go-module-support/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/swaggo/swag/example/go-module-support 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.9.1 7 | github.com/swaggo/examples v0.0.0-20190624100559-f57286ab550c 8 | github.com/swaggo/swag v1.8.1 9 | ) 10 | 11 | require ( 12 | github.com/KyleBanks/depth v1.2.1 // indirect 13 | github.com/PuerkitoBio/purell v1.1.1 // indirect 14 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 15 | github.com/bytedance/sonic v1.9.1 // indirect 16 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 17 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect 18 | github.com/gin-contrib/sse v0.1.0 // indirect 19 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 20 | github.com/go-openapi/jsonreference v0.19.6 // indirect 21 | github.com/go-openapi/spec v0.20.4 // indirect 22 | github.com/go-openapi/swag v0.19.15 // indirect 23 | github.com/go-playground/locales v0.14.1 // indirect 24 | github.com/go-playground/universal-translator v0.18.1 // indirect 25 | github.com/go-playground/validator/v10 v10.14.0 // indirect 26 | github.com/goccy/go-json v0.10.2 // indirect 27 | github.com/josharian/intern v1.0.0 // indirect 28 | github.com/json-iterator/go v1.1.12 // indirect 29 | github.com/klauspost/cpuid/v2 v2.2.4 // indirect 30 | github.com/leodido/go-urn v1.2.4 // indirect 31 | github.com/mailru/easyjson v0.7.6 // indirect 32 | github.com/mattn/go-isatty v0.0.19 // indirect 33 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 34 | github.com/modern-go/reflect2 v1.0.2 // indirect 35 | github.com/pelletier/go-toml/v2 v2.0.8 // indirect 36 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 37 | github.com/ugorji/go/codec v1.2.11 // indirect 38 | golang.org/x/arch v0.3.0 // indirect 39 | golang.org/x/crypto v0.21.0 // indirect 40 | golang.org/x/net v0.23.0 // indirect 41 | golang.org/x/sys v0.18.0 // indirect 42 | golang.org/x/text v0.14.0 // indirect 43 | golang.org/x/tools v0.6.0 // indirect 44 | google.golang.org/protobuf v1.33.0 // indirect 45 | gopkg.in/yaml.v2 v2.4.0 // indirect 46 | gopkg.in/yaml.v3 v3.0.1 // indirect 47 | ) 48 | -------------------------------------------------------------------------------- /example/go-module-support/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/swaggo/examples/go-module-support/api" // included package from external 6 | ) 7 | 8 | // @title Swagger Example API 9 | // @version 1.0 10 | // @description This is a sample server Petstore server. 11 | // @termsOfService http://swagger.io/terms/ 12 | 13 | // @contact.name API Support 14 | // @contact.url http://www.swagger.io/support 15 | // @contact.email support@swagger.io 16 | 17 | // @license.name Apache 2.0 18 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 19 | 20 | // @host petstore.swagger.io 21 | // @BasePath /v2 22 | 23 | func main() { 24 | r := gin.New() 25 | r.GET("/testapi/get-string-by-int/:some_id", api.GetStringByInt) 26 | r.GET("//testapi/get-struct-array-by-string/:some_id", api.GetStructArrayByString) 27 | r.Run() 28 | 29 | } 30 | -------------------------------------------------------------------------------- /example/go-module-support/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // Pet example 8 | type Pet struct { 9 | ID int `json:"id"` 10 | Category struct { 11 | ID int `json:"id"` 12 | Name string `json:"name"` 13 | } `json:"category"` 14 | Name string `json:"name"` 15 | PhotoUrls []string `json:"photoUrls"` 16 | Tags []Tag `json:"tags"` 17 | Status string `json:"status"` 18 | } 19 | 20 | // Tag example 21 | type Tag struct { 22 | ID int `json:"id"` 23 | Name string `json:"name"` 24 | } 25 | 26 | // Pet2 example 27 | type Pet2 struct { 28 | ID int `json:"id"` 29 | } 30 | 31 | // APIError example 32 | type APIError struct { 33 | ErrorCode int 34 | ErrorMessage string 35 | CreatedAt time.Time 36 | } 37 | 38 | // RevValueBase example 39 | type RevValueBase struct { 40 | Status bool `json:"Status"` 41 | 42 | Err int32 `json:"Err"` 43 | } 44 | 45 | // RevValue example 46 | type RevValue struct { 47 | RevValueBase 48 | 49 | Data int `json:"Data"` 50 | } 51 | -------------------------------------------------------------------------------- /example/markdown/admin.md: -------------------------------------------------------------------------------- 1 | # Admin TAG API documentation 2 | 3 | **Admin** functions goes here 4 | 5 | For more info please read [link](/docs/readme.md). 6 | 7 | -------------------------------------------------------------------------------- /example/markdown/api.md: -------------------------------------------------------------------------------- 1 | # General API documentation 2 | 3 | **Warning** this api is not production ready. Use at your own risk. 4 | 5 | In order to re-generate the documentation you need to run 6 | 7 | `swag init --md .` 8 | -------------------------------------------------------------------------------- /example/markdown/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | // User example 9 | type User struct { 10 | ID int64 11 | Email string 12 | Password string 13 | } 14 | 15 | // UsersCollection example 16 | type UsersCollection []User 17 | 18 | // Error example 19 | type APIError struct { 20 | ErrorCode int 21 | ErrorMessage string 22 | CreatedAt time.Time 23 | } 24 | 25 | // ListUsers example 26 | // 27 | // @Summary List users from the store 28 | // @Tags admin 29 | // @Accept json 30 | // @Produce json 31 | // @Success 200 {array} api.UsersCollection "ok" 32 | // @Router /admin/user/ [get] 33 | func ListUsers(w http.ResponseWriter, r *http.Request) { 34 | // write your code 35 | } 36 | 37 | // GetUser example 38 | // 39 | // @Summary Read user from the store 40 | // @Tags admin 41 | // @Accept json 42 | // @Produce json 43 | // @Param id path int true "User Id" 44 | // @Success 200 {object} api.User 45 | // @Failure 400 {object} api.APIError "We need ID!!" 46 | // @Failure 404 {object} api.APIError "Can not find ID" 47 | // @Router /admin/user/{id} [get] 48 | func GetUser(w http.ResponseWriter, r *http.Request) { 49 | // write your code 50 | } 51 | 52 | // AddUser example 53 | // 54 | // @Summary Add a new user to the store 55 | // @Tags admin 56 | // @Accept json 57 | // @Produce json 58 | // @Param message body api.User true "User Data" 59 | // @Success 200 {string} string "ok" 60 | // @Failure 400 {object} api.APIError "We need ID!!" 61 | // @Failure 404 {object} api.APIError "Can not find ID" 62 | // @Router /admin/user/ [post] 63 | func AddUser(w http.ResponseWriter, r *http.Request) { 64 | // write your code 65 | } 66 | 67 | // UpdateUser example 68 | // 69 | // @Summary Add a new user to the store 70 | // @Tags admin 71 | // @Accept json 72 | // @Produce json 73 | // @Param message body api.User true "User Data" 74 | // @Success 200 {string} string "ok" 75 | // @Failure 400 {object} api.APIError "We need ID!!" 76 | // @Failure 404 {object} api.APIError "Can not find ID" 77 | // @Router /admin/user/ [put] 78 | func UpdateUser(w http.ResponseWriter, r *http.Request) { 79 | // write your code 80 | } 81 | -------------------------------------------------------------------------------- /example/markdown/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/swaggo/swag/example/markdown 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/gorilla/mux v1.8.0 7 | github.com/swaggo/http-swagger v1.2.6 8 | github.com/swaggo/swag v1.8.1 9 | ) 10 | 11 | require ( 12 | github.com/KyleBanks/depth v1.2.1 // indirect 13 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 14 | github.com/go-openapi/jsonreference v0.20.0 // indirect 15 | github.com/go-openapi/spec v0.20.5 // indirect 16 | github.com/go-openapi/swag v0.19.15 // indirect 17 | github.com/josharian/intern v1.0.0 // indirect 18 | github.com/mailru/easyjson v0.7.6 // indirect 19 | github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 // indirect 20 | golang.org/x/net v0.23.0 // indirect 21 | golang.org/x/sys v0.18.0 // indirect 22 | golang.org/x/tools v0.1.10 // indirect 23 | gopkg.in/yaml.v2 v2.4.0 // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /example/markdown/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gorilla/mux" 7 | httpSwagger "github.com/swaggo/http-swagger" 8 | "github.com/swaggo/swag/example/markdown/api" 9 | _ "github.com/swaggo/swag/example/markdown/docs" 10 | ) 11 | 12 | // @title Swagger Example API 13 | // @version 1.0 14 | // @description This is a sample server Petstore server. 15 | // @description.markdown 16 | // @termsOfService http://swagger.io/terms/ 17 | 18 | // @contact.name API Support 19 | // @contact.url http://www.swagger.io/support 20 | // @contact.email support@swagger.io 21 | 22 | // @license.name Apache 2.0 23 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 24 | 25 | // @tag.name admin 26 | // @tag.description.markdown 27 | 28 | // @BasePath /v2 29 | 30 | func main() { 31 | router := mux.NewRouter() 32 | 33 | router.HandleFunc("/admin/user/", api.ListUsers).Methods("GET") 34 | router.HandleFunc("/admin/user/{id}", api.GetUser).Methods("GET") 35 | router.HandleFunc("/admin/user/", api.AddUser).Methods("POST") 36 | router.HandleFunc("/admin/user/{id}", api.UpdateUser).Methods("PUT") 37 | 38 | router.PathPrefix("/swagger/").Handler(httpSwagger.WrapHandler) 39 | http.ListenAndServe(":8080", router) 40 | } 41 | -------------------------------------------------------------------------------- /example/object-map-example/controller/api.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // GetMap godoc 6 | // 7 | // @Summary Get Map Example 8 | // @Description get map 9 | // @ID get-map 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} Response 13 | // @Router /test [get] 14 | func (c *Controller) GetMap(ctx *gin.Context) { 15 | ctx.JSON(200, Response{ 16 | Title: map[string]string{ 17 | "en": "Map", 18 | }, 19 | CustomType: map[string]interface{}{ 20 | "key": "value", 21 | }, 22 | Object: Data{ 23 | Text: "object text", 24 | }, 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /example/object-map-example/controller/controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | // Controller example 4 | type Controller struct { 5 | } 6 | 7 | // NewController example 8 | func NewController() *Controller { 9 | return &Controller{} 10 | } 11 | -------------------------------------------------------------------------------- /example/object-map-example/controller/response.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | type Response struct { 4 | Title map[string]string `json:"title" example:"en:Map,ru:Карта,kk:Карталар"` 5 | CustomType map[string]interface{} `json:"map_data" swaggertype:"object,string" example:"key:value,key2:value2"` 6 | Object Data `json:"object"` 7 | } 8 | 9 | type Data struct { 10 | Text string `json:"title" example:"Object data"` 11 | } 12 | -------------------------------------------------------------------------------- /example/object-map-example/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "Swagger Map Example API", 5 | "termsOfService": "http://swagger.io/terms/", 6 | "contact": {}, 7 | "license": { 8 | "name": "Apache 2.0", 9 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 10 | }, 11 | "version": "1.0" 12 | }, 13 | "host": "localhost:8080", 14 | "basePath": "/api/v1", 15 | "paths": { 16 | "/test": { 17 | "get": { 18 | "description": "get map", 19 | "consumes": [ 20 | "application/json" 21 | ], 22 | "produces": [ 23 | "application/json" 24 | ], 25 | "summary": "Get Map Example", 26 | "operationId": "get-map", 27 | "responses": { 28 | "200": { 29 | "description": "OK", 30 | "schema": { 31 | "$ref": "#/definitions/controller.Response" 32 | } 33 | } 34 | } 35 | } 36 | } 37 | }, 38 | "definitions": { 39 | "controller.Data": { 40 | "type": "object", 41 | "properties": { 42 | "title": { 43 | "type": "string", 44 | "example": "Object data" 45 | } 46 | } 47 | }, 48 | "controller.Response": { 49 | "type": "object", 50 | "properties": { 51 | "map_data": { 52 | "type": "object", 53 | "additionalProperties": { 54 | "type": "string" 55 | }, 56 | "example": { 57 | "key": "value", 58 | "key2": "value2" 59 | } 60 | }, 61 | "object": { 62 | "$ref": "#/definitions/controller.Data" 63 | }, 64 | "title": { 65 | "type": "object", 66 | "additionalProperties": { 67 | "type": "string" 68 | }, 69 | "example": { 70 | "en": "Map", 71 | "kk": "Карталар", 72 | "ru": "Карта" 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /example/object-map-example/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: /api/v1 2 | definitions: 3 | controller.Data: 4 | properties: 5 | title: 6 | example: Object data 7 | type: string 8 | type: object 9 | controller.Response: 10 | properties: 11 | map_data: 12 | additionalProperties: 13 | type: string 14 | example: 15 | key: value 16 | key2: value2 17 | type: object 18 | object: 19 | $ref: '#/definitions/controller.Data' 20 | title: 21 | additionalProperties: 22 | type: string 23 | example: 24 | en: Map 25 | kk: Карталар 26 | ru: Карта 27 | type: object 28 | type: object 29 | host: localhost:8080 30 | info: 31 | contact: {} 32 | license: 33 | name: Apache 2.0 34 | url: http://www.apache.org/licenses/LICENSE-2.0.html 35 | termsOfService: http://swagger.io/terms/ 36 | title: Swagger Map Example API 37 | version: "1.0" 38 | paths: 39 | /test: 40 | get: 41 | consumes: 42 | - application/json 43 | description: get map 44 | operationId: get-map 45 | produces: 46 | - application/json 47 | responses: 48 | "200": 49 | description: OK 50 | schema: 51 | $ref: '#/definitions/controller.Response' 52 | summary: Get Map Example 53 | swagger: "2.0" 54 | -------------------------------------------------------------------------------- /example/object-map-example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/swaggo/swag/example/object-map-example 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.9.1 7 | github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 8 | github.com/swaggo/gin-swagger v1.4.2 9 | github.com/swaggo/swag v1.8.1 10 | ) 11 | 12 | require ( 13 | github.com/KyleBanks/depth v1.2.1 // indirect 14 | github.com/bytedance/sonic v1.9.1 // indirect 15 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 16 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect 17 | github.com/gin-contrib/sse v0.1.0 // indirect 18 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 19 | github.com/go-openapi/jsonreference v0.20.0 // indirect 20 | github.com/go-openapi/spec v0.20.5 // indirect 21 | github.com/go-openapi/swag v0.19.15 // indirect 22 | github.com/go-playground/locales v0.14.1 // indirect 23 | github.com/go-playground/universal-translator v0.18.1 // indirect 24 | github.com/go-playground/validator/v10 v10.14.0 // indirect 25 | github.com/goccy/go-json v0.10.2 // indirect 26 | github.com/josharian/intern v1.0.0 // indirect 27 | github.com/json-iterator/go v1.1.12 // indirect 28 | github.com/klauspost/cpuid/v2 v2.2.4 // indirect 29 | github.com/leodido/go-urn v1.2.4 // indirect 30 | github.com/mailru/easyjson v0.7.6 // indirect 31 | github.com/mattn/go-isatty v0.0.19 // indirect 32 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 33 | github.com/modern-go/reflect2 v1.0.2 // indirect 34 | github.com/pelletier/go-toml/v2 v2.0.8 // indirect 35 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 36 | github.com/ugorji/go/codec v1.2.11 // indirect 37 | golang.org/x/arch v0.3.0 // indirect 38 | golang.org/x/crypto v0.31.0 // indirect 39 | golang.org/x/net v0.25.0 // indirect 40 | golang.org/x/sys v0.28.0 // indirect 41 | golang.org/x/text v0.21.0 // indirect 42 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect 43 | google.golang.org/protobuf v1.33.0 // indirect 44 | gopkg.in/yaml.v2 v2.4.0 // indirect 45 | gopkg.in/yaml.v3 v3.0.1 // indirect 46 | ) 47 | -------------------------------------------------------------------------------- /example/object-map-example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/swaggo/swag/example/object-map-example/controller" 6 | _ "github.com/swaggo/swag/example/object-map-example/docs" 7 | 8 | swaggerFiles "github.com/swaggo/files" 9 | ginSwagger "github.com/swaggo/gin-swagger" 10 | ) 11 | 12 | // @title Swagger Map Example API 13 | // @version 1.0 14 | // @termsOfService http://swagger.io/terms/ 15 | 16 | // @license.name Apache 2.0 17 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 18 | 19 | // @host localhost:8080 20 | // @BasePath /api/v1 21 | 22 | func main() { 23 | r := gin.Default() 24 | 25 | c := controller.NewController() 26 | 27 | v1 := r.Group("/api/v1") 28 | { 29 | test := v1.Group("/map") 30 | { 31 | test.GET("", c.GetMap) 32 | } 33 | } 34 | r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) 35 | r.Run(":8080") 36 | } 37 | -------------------------------------------------------------------------------- /example/override/.swaggo: -------------------------------------------------------------------------------- 1 | replace sql.NullString string 2 | replace sql.NullInt64 int64 3 | -------------------------------------------------------------------------------- /example/override/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server for updating product information.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "host": "product_info.swagger.io", 19 | "basePath": "/v2", 20 | "paths": { 21 | "/testapi/update-product/{product_id}": { 22 | "post": { 23 | "consumes": [ 24 | "application/json" 25 | ], 26 | "summary": "Update product attributes", 27 | "operationId": "update-product", 28 | "parameters": [ 29 | { 30 | "type": "integer", 31 | "description": "Product ID", 32 | "name": "product_id", 33 | "in": "path", 34 | "required": true 35 | }, 36 | { 37 | "description": " ", 38 | "name": "_", 39 | "in": "body", 40 | "required": true, 41 | "schema": { 42 | "$ref": "#/definitions/main.ProductUpdates" 43 | } 44 | } 45 | ], 46 | "responses": {} 47 | } 48 | } 49 | }, 50 | "definitions": { 51 | "main.ProductUpdates": { 52 | "type": "object", 53 | "properties": { 54 | "description": { 55 | "type": "string" 56 | }, 57 | "stock": { 58 | "type": "integer" 59 | }, 60 | "type": { 61 | "type": "string" 62 | } 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /example/override/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: /v2 2 | definitions: 3 | main.ProductUpdates: 4 | properties: 5 | description: 6 | type: string 7 | stock: 8 | type: integer 9 | type: 10 | type: string 11 | type: object 12 | host: product_info.swagger.io 13 | info: 14 | contact: 15 | email: support@swagger.io 16 | name: API Support 17 | url: http://www.swagger.io/support 18 | description: This is a sample server for updating product information. 19 | license: 20 | name: Apache 2.0 21 | url: http://www.apache.org/licenses/LICENSE-2.0.html 22 | termsOfService: http://swagger.io/terms/ 23 | title: Swagger Example API 24 | version: "1.0" 25 | paths: 26 | /testapi/update-product/{product_id}: 27 | post: 28 | consumes: 29 | - application/json 30 | operationId: update-product 31 | parameters: 32 | - description: Product ID 33 | in: path 34 | name: product_id 35 | required: true 36 | type: integer 37 | - description: ' ' 38 | in: body 39 | name: _ 40 | required: true 41 | schema: 42 | $ref: '#/definitions/main.ProductUpdates' 43 | responses: {} 44 | summary: Update product attributes 45 | swagger: "2.0" 46 | -------------------------------------------------------------------------------- /example/override/handler.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "encoding/json" 6 | "net/http" 7 | ) 8 | 9 | type ProductUpdates struct { 10 | Type sql.NullString `json:"type"` 11 | Description sql.NullString `json:"description"` 12 | Stock sql.NullInt64 `json:"stock"` 13 | } 14 | 15 | // UpdateProduct example 16 | // 17 | // @Summary Update product attributes 18 | // @ID update-product 19 | // @Accept json 20 | // @Param product_id path int true "Product ID" 21 | // @Param _ body ProductUpdates true " " 22 | // @Router /testapi/update-product/{product_id} [post] 23 | func UpdateProduct(w http.ResponseWriter, r *http.Request) { 24 | var pUpdates ProductUpdates 25 | if err := json.NewDecoder(r.Body).Decode(&pUpdates); err != nil { 26 | // write your code 27 | return 28 | } 29 | 30 | // write your code 31 | } 32 | -------------------------------------------------------------------------------- /example/override/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // @title Swagger Example API 8 | // @version 1.0 9 | // @description This is a sample server with null types overridden with primitive types. 10 | // @termsOfService http://swagger.io/terms/ 11 | 12 | // @contact.name API Support 13 | // @contact.url http://www.swagger.io/support 14 | // @contact.email support@swagger.io 15 | 16 | // @license.name Apache 2.0 17 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 18 | 19 | // @host product_info.swagger.io 20 | // @BasePath /v2 21 | 22 | func main() { 23 | http.HandleFunc("/testapi/update-product", UpdateProduct) 24 | http.ListenAndServe(":8080", nil) 25 | } 26 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/swaggo/swag 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/KyleBanks/depth v1.2.1 7 | github.com/go-openapi/spec v0.20.4 8 | github.com/stretchr/testify v1.7.0 9 | github.com/urfave/cli/v2 v2.3.0 10 | golang.org/x/text v0.21.0 11 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d 12 | sigs.k8s.io/yaml v1.3.0 13 | ) 14 | 15 | require ( 16 | github.com/PuerkitoBio/purell v1.1.1 // indirect 17 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 18 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect 19 | github.com/davecgh/go-spew v1.1.1 // indirect 20 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 21 | github.com/go-openapi/jsonreference v0.19.6 // indirect 22 | github.com/go-openapi/swag v0.19.15 // indirect 23 | github.com/josharian/intern v1.0.0 // indirect 24 | github.com/mailru/easyjson v0.7.6 // indirect 25 | github.com/pmezard/go-difflib v1.0.0 // indirect 26 | github.com/russross/blackfriday/v2 v2.0.1 // indirect 27 | github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect 28 | golang.org/x/mod v0.17.0 // indirect 29 | golang.org/x/net v0.34.0 // indirect 30 | gopkg.in/yaml.v2 v2.4.0 // indirect 31 | gopkg.in/yaml.v3 v3.0.0 // indirect 32 | ) 33 | 34 | retract ( 35 | v1.16.0 // published accidentally 36 | v1.9.0 // published accidentally 37 | ) 38 | -------------------------------------------------------------------------------- /golist.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "encoding/json" 7 | "fmt" 8 | "go/build" 9 | "os/exec" 10 | "path/filepath" 11 | ) 12 | 13 | func listPackages(ctx context.Context, dir string, env []string, args ...string) (pkgs []*build.Package, finalErr error) { 14 | cmd := exec.CommandContext(ctx, "go", append([]string{"list", "-json", "-e"}, args...)...) 15 | cmd.Env = env 16 | cmd.Dir = dir 17 | 18 | stdout, err := cmd.StdoutPipe() 19 | if err != nil { 20 | return nil, err 21 | } 22 | var stderrBuf bytes.Buffer 23 | cmd.Stderr = &stderrBuf 24 | defer func() { 25 | if (finalErr != nil) && (stderrBuf.Len() > 0) { 26 | finalErr = fmt.Errorf("%v\n%s", finalErr, stderrBuf.Bytes()) 27 | } 28 | }() 29 | 30 | err = cmd.Start() 31 | if err != nil { 32 | return nil, err 33 | } 34 | dec := json.NewDecoder(stdout) 35 | for dec.More() { 36 | var pkg build.Package 37 | err = dec.Decode(&pkg) 38 | if err != nil { 39 | return nil, err 40 | } 41 | pkgs = append(pkgs, &pkg) 42 | } 43 | err = cmd.Wait() 44 | if err != nil { 45 | return nil, err 46 | } 47 | return pkgs, nil 48 | } 49 | 50 | func (parser *Parser) getAllGoFileInfoFromDepsByList(pkg *build.Package, parseFlag ParseFlag) error { 51 | ignoreInternal := pkg.Goroot && !parser.ParseInternal 52 | if ignoreInternal { // ignored internal 53 | return nil 54 | } 55 | 56 | if parser.skipPackageByPrefix(pkg.ImportPath) { 57 | return nil // ignored by user-defined package path prefixes 58 | } 59 | 60 | srcDir := pkg.Dir 61 | var err error 62 | for i := range pkg.GoFiles { 63 | err = parser.parseFile(pkg.ImportPath, filepath.Join(srcDir, pkg.GoFiles[i]), nil, parseFlag) 64 | if err != nil { 65 | return err 66 | } 67 | } 68 | 69 | // parse .go source files that import "C" 70 | for i := range pkg.CgoFiles { 71 | err = parser.parseFile(pkg.ImportPath, filepath.Join(srcDir, pkg.CgoFiles[i]), nil, parseFlag) 72 | if err != nil { 73 | return err 74 | } 75 | } 76 | 77 | return nil 78 | } 79 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Eason Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /spec.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "strings" 7 | "text/template" 8 | ) 9 | 10 | // Spec holds exported Swagger Info so clients can modify it. 11 | type Spec struct { 12 | Version string 13 | Host string 14 | BasePath string 15 | Schemes []string 16 | Title string 17 | Description string 18 | InfoInstanceName string 19 | SwaggerTemplate string 20 | LeftDelim string 21 | RightDelim string 22 | } 23 | 24 | // ReadDoc parses SwaggerTemplate into swagger document. 25 | func (i *Spec) ReadDoc() string { 26 | i.Description = strings.ReplaceAll(i.Description, "\n", "\\n") 27 | 28 | tpl := template.New("swagger_info").Funcs(template.FuncMap{ 29 | "marshal": func(v interface{}) string { 30 | a, _ := json.Marshal(v) 31 | 32 | return string(a) 33 | }, 34 | "escape": func(v interface{}) string { 35 | // escape tabs 36 | var str = strings.ReplaceAll(v.(string), "\t", "\\t") 37 | // replace " with \", and if that results in \\", replace that with \\\" 38 | str = strings.ReplaceAll(str, "\"", "\\\"") 39 | 40 | return strings.ReplaceAll(str, "\\\\\"", "\\\\\\\"") 41 | }, 42 | }) 43 | 44 | if i.LeftDelim != "" && i.RightDelim != "" { 45 | tpl = tpl.Delims(i.LeftDelim, i.RightDelim) 46 | } 47 | 48 | parsed, err := tpl.Parse(i.SwaggerTemplate) 49 | if err != nil { 50 | return i.SwaggerTemplate 51 | } 52 | 53 | var doc bytes.Buffer 54 | if err = parsed.Execute(&doc, i); err != nil { 55 | return i.SwaggerTemplate 56 | } 57 | 58 | return doc.String() 59 | } 60 | 61 | // InstanceName returns Spec instance name. 62 | func (i *Spec) InstanceName() string { 63 | return i.InfoInstanceName 64 | } 65 | -------------------------------------------------------------------------------- /swagger.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "sync" 7 | ) 8 | 9 | // Name is a unique name be used to register swag instance. 10 | const Name = "swagger" 11 | 12 | var ( 13 | swaggerMu sync.RWMutex 14 | swags map[string]Swagger 15 | ) 16 | 17 | // Swagger is an interface to read swagger document. 18 | type Swagger interface { 19 | ReadDoc() string 20 | } 21 | 22 | // Register registers swagger for given name. 23 | func Register(name string, swagger Swagger) { 24 | swaggerMu.Lock() 25 | defer swaggerMu.Unlock() 26 | 27 | if swagger == nil { 28 | panic("swagger is nil") 29 | } 30 | 31 | if swags == nil { 32 | swags = make(map[string]Swagger) 33 | } 34 | 35 | if _, ok := swags[name]; ok { 36 | panic("Register called twice for swag: " + name) 37 | } 38 | 39 | swags[name] = swagger 40 | } 41 | 42 | // GetSwagger returns the swagger instance for given name. 43 | // If not found, returns nil. 44 | func GetSwagger(name string) Swagger { 45 | swaggerMu.RLock() 46 | defer swaggerMu.RUnlock() 47 | 48 | return swags[name] 49 | } 50 | 51 | // ReadDoc reads swagger document. An optional name parameter can be passed to read a specific document. 52 | // The default name is "swagger". 53 | func ReadDoc(optionalName ...string) (string, error) { 54 | swaggerMu.RLock() 55 | defer swaggerMu.RUnlock() 56 | 57 | if swags == nil { 58 | return "", errors.New("no swag has yet been registered") 59 | } 60 | 61 | name := Name 62 | if len(optionalName) != 0 && optionalName[0] != "" { 63 | name = optionalName[0] 64 | } 65 | 66 | swag, ok := swags[name] 67 | if !ok { 68 | return "", fmt.Errorf("no swag named \"%s\" was registered", name) 69 | } 70 | 71 | return swag.ReadDoc(), nil 72 | } 73 | -------------------------------------------------------------------------------- /testdata/alias_import/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/swaggo/swag/testdata/alias_import/data" 8 | "github.com/swaggo/swag/testdata/alias_type/types" 9 | ) 10 | 11 | // @Summary Get application 12 | // @Description test get application 13 | // @ID get-application 14 | // @Accept json 15 | // @Produce json 16 | // @Success 200 {object} data.ApplicationResponse "ok" 17 | // @Router /testapi/application [get] 18 | func GetApplication(w http.ResponseWriter, r *http.Request) { 19 | var foo = data.ApplicationResponse{ 20 | Application: types.Application{ 21 | Name: "name", 22 | }, 23 | ApplicationArray: []types.Application{ 24 | {Name: "name"}, 25 | }, 26 | } 27 | log.Println(foo) 28 | //write your code 29 | } 30 | -------------------------------------------------------------------------------- /testdata/alias_import/data/applicationresponse.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | typesapplication "github.com/swaggo/swag/testdata/alias_import/types" 5 | ) 6 | 7 | type ApplicationResponse struct { 8 | typesapplication.TypeToEmbed 9 | 10 | Application typesapplication.Application `json:"application"` 11 | ApplicationArray []typesapplication.Application `json:"application_array"` 12 | ApplicationTime typesapplication.DateOnly `json:"application_time"` 13 | } 14 | -------------------------------------------------------------------------------- /testdata/alias_import/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server Petstore server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "host": "petstore.swagger.io", 19 | "basePath": "/v2", 20 | "paths": { 21 | "/testapi/application": { 22 | "get": { 23 | "description": "test get application", 24 | "consumes": [ 25 | "application/json" 26 | ], 27 | "produces": [ 28 | "application/json" 29 | ], 30 | "summary": "Get application", 31 | "operationId": "get-application", 32 | "responses": { 33 | "200": { 34 | "description": "ok", 35 | "schema": { 36 | "$ref": "#/definitions/data.ApplicationResponse" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }, 43 | "definitions": { 44 | "data.ApplicationResponse": { 45 | "type": "object", 46 | "properties": { 47 | "application": { 48 | "$ref": "#/definitions/types.Application" 49 | }, 50 | "application_array": { 51 | "type": "array", 52 | "items": { 53 | "$ref": "#/definitions/types.Application" 54 | } 55 | }, 56 | "application_time": { 57 | "type": "string" 58 | }, 59 | "embedded": { 60 | "type": "string" 61 | } 62 | } 63 | }, 64 | "types.Application": { 65 | "type": "object", 66 | "properties": { 67 | "name": { 68 | "type": "string" 69 | } 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /testdata/alias_import/main.go: -------------------------------------------------------------------------------- 1 | package alias_import 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/alias_import/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | func main() { 24 | http.HandleFunc("/testapi/application", api.GetApplication) 25 | http.ListenAndServe(":8080", nil) 26 | } 27 | -------------------------------------------------------------------------------- /testdata/alias_import/types/application.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "time" 4 | 5 | type Application struct { 6 | Name string 7 | } 8 | 9 | type DateOnly time.Time 10 | 11 | type TypeToEmbed struct { 12 | Embedded string 13 | } 14 | -------------------------------------------------------------------------------- /testdata/alias_nested/cmd/main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/swaggo/swag/testdata/alias_nested/pkg/good" 4 | 5 | // @Success 200 {object} good.Gen 6 | // @Router /api [get]. 7 | func main() { 8 | var _ good.Gen 9 | } 10 | -------------------------------------------------------------------------------- /testdata/alias_nested/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {} 5 | }, 6 | "paths": { 7 | "/api": { 8 | "get": { 9 | "responses": { 10 | "200": { 11 | "description": "OK", 12 | "schema": { 13 | "$ref": "#/definitions/Gen" 14 | } 15 | } 16 | } 17 | } 18 | } 19 | }, 20 | "definitions": { 21 | "Gen": { 22 | "type": "object", 23 | "properties": { 24 | "emb": { 25 | "$ref": "#/definitions/github_com_swaggo_swag_testdata_alias_nested_pkg_good.Emb" 26 | } 27 | } 28 | }, 29 | "github_com_swaggo_swag_testdata_alias_nested_pkg_good.Emb": { 30 | "type": "object", 31 | "properties": { 32 | "good": { 33 | "type": "boolean" 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /testdata/alias_nested/pkg/bad/data.go: -------------------------------------------------------------------------------- 1 | package bad 2 | 3 | type Emb struct { 4 | Bad bool `json:"bad"` 5 | } // @name Emb 6 | -------------------------------------------------------------------------------- /testdata/alias_nested/pkg/good/data.go: -------------------------------------------------------------------------------- 1 | package good 2 | 3 | type Gen struct { 4 | Emb Emb `json:"emb"` 5 | } // @name Gen 6 | 7 | type Emb struct { 8 | Good bool `json:"good"` 9 | } 10 | -------------------------------------------------------------------------------- /testdata/alias_type/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/swaggo/swag/testdata/alias_type/data" 9 | ) 10 | 11 | /*// @Summary Get time as string 12 | // @Description get time as string 13 | // @ID time-as-string 14 | // @Accept json 15 | // @Produce json 16 | // @Success 200 {object} data.StringAlias "ok" 17 | // @Router /testapi/time-as-string [get] 18 | func GetTimeAsStringAlias(w http.ResponseWriter, r *http.Request) { 19 | var foo data.StringAlias = "test" 20 | log.Println(foo) 21 | //write your code 22 | }*/ 23 | 24 | /*// @Summary Get time as time 25 | // @Description get time as time 26 | // @ID time-as-time 27 | // @Accept json 28 | // @Produce json 29 | // @Success 200 {object} data.DateOnly "ok" 30 | // @Router /testapi/time-as-time [get] 31 | func GetTimeAsTimeAlias(w http.ResponseWriter, r *http.Request) { 32 | var foo = data.DateOnly(time.Now()) 33 | log.Println(foo) 34 | //write your code 35 | }*/ 36 | 37 | // @Summary Get container with time and time alias 38 | // @Description test container with time and time alias 39 | // @ID time-as-time-container 40 | // @Accept json 41 | // @Produce json 42 | // @Success 200 {object} data.TimeContainer "ok" 43 | // @Router /testapi/time-as-time-container [get] 44 | func GetTimeAsTimeContainer(w http.ResponseWriter, r *http.Request) { 45 | now := time.Now() 46 | var foo = data.TimeContainer{ 47 | Name: "test", 48 | Timestamp: now, 49 | //CreatedAt: &now, 50 | } 51 | log.Println(foo) 52 | //write your code 53 | } 54 | -------------------------------------------------------------------------------- /testdata/alias_type/data/alias.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "github.com/swaggo/swag/testdata/alias_type/types" 5 | "time" 6 | ) 7 | 8 | type TimeContainer struct { 9 | Name types.StringAlias `json:"name"` 10 | Timestamp time.Time `json:"timestamp"` 11 | CreatedAt types.DateOnly `json:"created_at"` 12 | } 13 | -------------------------------------------------------------------------------- /testdata/alias_type/main.go: -------------------------------------------------------------------------------- 1 | package alias_type 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/alias_type/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | func main() { 24 | http.HandleFunc("/testapi/time-as-time-container", api.GetTimeAsTimeContainer) 25 | http.ListenAndServe(":8080", nil) 26 | } 27 | -------------------------------------------------------------------------------- /testdata/alias_type/types/alias.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "time" 4 | 5 | type StringAlias string 6 | 7 | type DateOnly time.Time 8 | -------------------------------------------------------------------------------- /testdata/api.md: -------------------------------------------------------------------------------- 1 | Swagger Example API Markdown Description -------------------------------------------------------------------------------- /testdata/code_examples/api/api1.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | _ "github.com/swaggo/swag/testdata/conflict_name/model" 5 | "net/http" 6 | ) 7 | 8 | // @Description Check if Health of service it's OK! 9 | // @Router /health [get] 10 | // @x-codeSamples file 11 | func Get1(w http.ResponseWriter, r *http.Request) { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /testdata/code_examples/broken.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": value 3 | } -------------------------------------------------------------------------------- /testdata/code_examples/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": "JavaScript", 3 | "source": "console.log('Hello World');" 4 | } -------------------------------------------------------------------------------- /testdata/code_examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swag test 4 | // @version 1.0 5 | // @description test for conflict name 6 | func main() { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /testdata/composition/common/response.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | type ResponseFormat struct { 4 | Message string `json:"message"` 5 | } 6 | -------------------------------------------------------------------------------- /testdata/composition/main.go: -------------------------------------------------------------------------------- 1 | package composition 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/composition/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @host petstore.swagger.io 15 | // @BasePath /v2 16 | 17 | func main() { 18 | http.handleFunc("/testapi/get-foo", api.GetFoo) 19 | http.handleFunc("/testapi/get-bar", api.GetBar) 20 | http.handleFunc("/testapi/get-foobar", api.GetFooBar) 21 | http.handleFunc("/testapi/get-foobar-pointer", api.GetFooBarPointer) 22 | http.handleFunc("/testapi/get-barmap", api.GetBarMap) 23 | http.ListenAndServe(":8080", nil) 24 | } 25 | -------------------------------------------------------------------------------- /testdata/conflict_name/api/api1.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | _ "github.com/swaggo/swag/testdata/conflict_name/model" 5 | "net/http" 6 | ) 7 | 8 | // @Tags Health 9 | // @Description Check if Health of service it's OK! 10 | // @ID health 11 | // @Accept json 12 | // @Produce json 13 | // @Success 200 {object} model.ErrorsResponse 14 | // @Router /health [get] 15 | func Get1(w http.ResponseWriter, r *http.Request) { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /testdata/conflict_name/api/api2.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | _ "github.com/swaggo/swag/testdata/conflict_name/model2" 5 | "net/http" 6 | ) 7 | 8 | // @Tags Health 9 | // @Description Check if Health of service it's OK! 10 | // @ID health2 11 | // @Accept json 12 | // @Produce json 13 | // @Success 200 {object} model.ErrorsResponse 14 | // @Router /health2 [get] 15 | func Get2(w http.ResponseWriter, r *http.Request) { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /testdata/conflict_name/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swag test 4 | // @version 1.0 5 | // @description test for conflict name 6 | func main() { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /testdata/conflict_name/model/model.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type MyStruct struct { 4 | Name string `json:"name"` 5 | } 6 | 7 | type MyPayload struct { 8 | My MyStruct 9 | Name string `json:"name"` 10 | } 11 | 12 | type ErrorsResponse struct { 13 | NewTime MyPayload 14 | } 15 | -------------------------------------------------------------------------------- /testdata/conflict_name/model2/model.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type MyStruct struct { 4 | Name string `json:"name"` 5 | } 6 | 7 | type MyPayload2 struct { 8 | My MyStruct 9 | Name string `json:"name"` 10 | } 11 | 12 | type ErrorsResponse struct { 13 | NewTime MyPayload2 14 | } 15 | -------------------------------------------------------------------------------- /testdata/delims/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // MyFunc godoc 4 | // @Description My Function 5 | // @Success 200 {object} MyStruct 6 | // @Router /myfunc [get] 7 | func MyFunc() {} 8 | 9 | type MyStruct struct { 10 | URLTemplate string `json:"urltemplate" example:"http://example.org/{{ path }}" swaggertype:"string"` 11 | } 12 | -------------------------------------------------------------------------------- /testdata/delims/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemes": [], 3 | "swagger": "2.0", 4 | "info": { 5 | "description": "Testing custom template delimeters", 6 | "title": "Swagger Example API", 7 | "termsOfService": "http://swagger.io/terms/", 8 | "contact": {}, 9 | "version": "1.0" 10 | }, 11 | "host": "", 12 | "basePath": "", 13 | "paths": { 14 | "/myfunc": { 15 | "get": { 16 | "description": "My Function", 17 | "responses": { 18 | "200": { 19 | "description": "OK", 20 | "schema": { 21 | "$ref": "#/definitions/api.MyStruct" 22 | } 23 | } 24 | } 25 | } 26 | } 27 | }, 28 | "definitions": { 29 | "api.MyStruct": { 30 | "type": "object", 31 | "properties": { 32 | "urltemplate": { 33 | "type": "string", 34 | "example": "http://example.org/{{ path }}" 35 | } 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /testdata/delims/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/swaggo/swag" 5 | "github.com/swaggo/swag/testdata/delims/api" 6 | _ "github.com/swaggo/swag/testdata/delims/docs" 7 | ) 8 | 9 | func ReadDoc() string { 10 | doc, _ := swag.ReadDoc("CustomDelims") 11 | return doc 12 | } 13 | 14 | // @title Swagger Example API 15 | // @version 1.0 16 | // @description Testing custom template delimeters 17 | // @termsOfService http://swagger.io/terms/ 18 | 19 | func main() { 20 | api.MyFunc() 21 | } 22 | -------------------------------------------------------------------------------- /testdata/deprecated_router/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Description add Foo 6 | // @Deprecated 7 | // @Success 200 {string} string 8 | // @Router /testapi/foo1 [put] 9 | // @Router /testapi/foo1 [post] 10 | // @Router /test/api/foo1 [post] 11 | func AddFoo(w http.ResponseWriter, r *http.Request) {} 12 | 13 | // @Description get Foo 14 | // @Success 200 {string} string 15 | // @Router /testapi/foo1 [get] 16 | // @DeprecatedRouter /test/api/foo1 [get] 17 | func GetFoo(w http.ResponseWriter, r *http.Request) {} 18 | -------------------------------------------------------------------------------- /testdata/deprecated_router/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "test data for deprecated router", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": {}, 8 | "version": "1.0" 9 | }, 10 | "paths": { 11 | "/test/api/foo1": { 12 | "get": { 13 | "description": "get Foo", 14 | "deprecated": true, 15 | "responses": { 16 | "200": { 17 | "description": "OK", 18 | "schema": { 19 | "type": "string" 20 | } 21 | } 22 | } 23 | }, 24 | "post": { 25 | "description": "add Foo", 26 | "deprecated": true, 27 | "responses": { 28 | "200": { 29 | "description": "OK", 30 | "schema": { 31 | "type": "string" 32 | } 33 | } 34 | } 35 | } 36 | }, 37 | "/testapi/foo1": { 38 | "get": { 39 | "description": "get Foo", 40 | "responses": { 41 | "200": { 42 | "description": "OK", 43 | "schema": { 44 | "type": "string" 45 | } 46 | } 47 | } 48 | }, 49 | "put": { 50 | "description": "add Foo", 51 | "deprecated": true, 52 | "responses": { 53 | "200": { 54 | "description": "OK", 55 | "schema": { 56 | "type": "string" 57 | } 58 | } 59 | } 60 | }, 61 | "post": { 62 | "description": "add Foo", 63 | "deprecated": true, 64 | "responses": { 65 | "200": { 66 | "description": "OK", 67 | "schema": { 68 | "type": "string" 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /testdata/deprecated_router/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description test data for deprecated router 6 | // @termsOfService http://swagger.io/terms/ 7 | 8 | func main() { 9 | } 10 | -------------------------------------------------------------------------------- /testdata/deps_having_invalid_pkg/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import _ "golang.org/x/tools/go/loader" // it inside contains invalid package files 4 | func main() {} 5 | -------------------------------------------------------------------------------- /testdata/duplicated/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Description get Foo 6 | // @ID get-foo 7 | // @Success 200 {string} string 8 | // @Router /testapi/get-foo [get] 9 | func GetFoo(w http.ResponseWriter, r *http.Request) {} 10 | 11 | // @Description post Bar 12 | // @ID get-foo 13 | // @Success 200 {string} string 14 | // @Router /testapi/post-bar [post] 15 | func PostBar(w http.ResponseWriter, r *http.Request) {} 16 | -------------------------------------------------------------------------------- /testdata/duplicated/main.go: -------------------------------------------------------------------------------- 1 | package composition 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/duplicated/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @host petstore.swagger.io 15 | // @BasePath /v2 16 | 17 | func main() { 18 | http.HandleFunc("/testapi/get-foo", api.GetFoo) 19 | http.HandleFunc("/testapi/post-bar", api.PostBar) 20 | http.ListenAndServe(":8080", nil) 21 | } 22 | -------------------------------------------------------------------------------- /testdata/duplicated2/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Description put Foo 6 | // @ID put-foo 7 | // @Success 200 {string} string 8 | // @Router /testapi/put-foo [put] 9 | func PutFoo(w http.ResponseWriter, r *http.Request) {} 10 | 11 | // @Description head Foo 12 | // @ID head-foo 13 | // @Success 200 {string} string 14 | // @Router /testapi/head-foo [head] 15 | func HeadFoo(w http.ResponseWriter, r *http.Request) {} 16 | 17 | // @Description options Foo 18 | // @ID options-foo 19 | // @Success 200 {string} string 20 | // @Router /testapi/options-foo [options] 21 | func OptionsFoo(w http.ResponseWriter, r *http.Request) {} 22 | 23 | // @Description patch Foo 24 | // @ID patch-foo 25 | // @Success 200 {string} string 26 | // @Router /testapi/patch-foo [patch] 27 | func PatchFoo(w http.ResponseWriter, r *http.Request) {} 28 | 29 | // @Description delete Foo 30 | // @ID put-foo 31 | // @Success 200 {string} string 32 | // @Router /testapi/delete-foo [delete] 33 | func DeleteFoo(w http.ResponseWriter, r *http.Request) {} 34 | -------------------------------------------------------------------------------- /testdata/duplicated2/main.go: -------------------------------------------------------------------------------- 1 | package composition 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/duplicated2/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @host petstore.swagger.io 15 | // @BasePath /v2 16 | 17 | func main() { 18 | http.HandleFunc("/testapi/put-foo", api.PutFoo) 19 | http.HandleFunc("/testapi/head-foo", api.HeadFoo) 20 | http.HandleFunc("/testapi/options-foo", api.OptionsFoo) 21 | http.HandleFunc("/testapi/patch-foo", api.PatchFoo) 22 | http.HandleFunc("/testapi/delete-foo", api.DeleteFoo) 23 | http.ListenAndServe(":8080", nil) 24 | } 25 | -------------------------------------------------------------------------------- /testdata/duplicated_function_scoped/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Description get Foo 6 | // @ID get-foo 7 | // @Success 200 {object} api.GetFoo.response 8 | // @Router /testapi/get-foo [get] 9 | func GetFoo(w http.ResponseWriter, r *http.Request) { 10 | type response struct { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /testdata/duplicated_function_scoped/main.go: -------------------------------------------------------------------------------- 1 | package composition 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/duplicated_function_scoped/api" 7 | otherapi "github.com/swaggo/swag/testdata/duplicated_function_scoped/other_api" 8 | ) 9 | 10 | // @title Swagger Example API 11 | // @version 1.0 12 | // @description This is a sample server 13 | // @termsOfService http://swagger.io/terms/ 14 | 15 | // @host petstore.swagger.io 16 | // @BasePath /v2 17 | 18 | func main() { 19 | http.HandleFunc("/testapi/get-foo", api.GetFoo) 20 | http.HandleFunc("/testapi/post-bar", otherapi.GetFoo) 21 | http.ListenAndServe(":8080", nil) 22 | } 23 | -------------------------------------------------------------------------------- /testdata/duplicated_function_scoped/other_api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Description get Foo 6 | // @ID get-foo 7 | // @Success 200 {object} api.GetFoo.response 8 | // @Router /testapi/get-foo [get] 9 | func GetFoo(w http.ResponseWriter, r *http.Request) { 10 | type response struct { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /testdata/enums/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "github.com/swaggo/swag/testdata/enums/types" 4 | 5 | // post students 6 | // 7 | // @Summary test enums in response models 8 | // @Description test enums in response models 9 | // @Failure 400 {object} types.Person "ok" 10 | // @Router /students [post] 11 | func API() { 12 | _ = types.Person{} 13 | } 14 | 15 | // get students 16 | // 17 | // @Summary test enums in response request 18 | // @Description test enums in response request 19 | // @Param typeinquery query []types.Type true "type" 20 | // @Param typeinheader header types.Type true "type" 21 | // @Param typeinpath path types.Type true "type" 22 | // @Success 200 "ok" 23 | // @Router /students/{typeinpath}/ [get] 24 | func API2() { 25 | _ = types.Person{} 26 | } 27 | 28 | // post students 29 | // 30 | // @Summary test enums fields in formdata request 31 | // @Description test enums fields in formdata request 32 | // @Param student formData types.Person true "type" 33 | // @Success 200 "ok" 34 | // @Router /students2 [get] 35 | func API3() { 36 | _ = types.Person{} 37 | } 38 | 39 | // post students 40 | // 41 | // @Summary test array enums fields in formdata request 42 | // @Description test array enums fields in formdata request 43 | // @Param student formData types.PersonWithArrayEnum true "type" 44 | // @Success 200 "ok" 45 | // @Router /students4 [get] 46 | func API4() { 47 | _ = types.Person{} 48 | } 49 | -------------------------------------------------------------------------------- /testdata/enums/consts/const.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | const Base = 1 4 | 5 | const uintSize = 32 << (^uint(uintptr(0)) >> 63) 6 | const maxBase = 10 + ('z' - 'a' + 1) + ('Z' - 'A' + 1) 7 | const shlByLen = 1 << len("aaa") 8 | const hexnum = 0xFF 9 | const octnum = 017 10 | const nonescapestr = `aa\nbb\u8888cc` 11 | const escapestr = "aa\nbb\u8888cc" 12 | const escapechar = '\u8888' 13 | const underscored = 1_000_000 14 | const binaryInteger = 0b10001000 15 | -------------------------------------------------------------------------------- /testdata/enums/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description This is a sample server. 6 | // @termsOfService http://swagger.io/terms/ 7 | 8 | // @contact.name API Support 9 | // @contact.url http://www.swagger.io/support 10 | // @contact.email support@swagger.io 11 | 12 | // @license.name Apache 2.0 13 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 14 | 15 | // @BasePath /v2 16 | func main() { 17 | } 18 | -------------------------------------------------------------------------------- /testdata/enums/types/model.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/swaggo/swag/testdata/enums/consts" 5 | ) 6 | 7 | type Class int 8 | 9 | const ( 10 | None Class = -1 11 | A Class = consts.Base + (iota+1-1)*2/2%100 - (1&1 | 1) + (2 ^ 2) // AAA 12 | B /* BBB */ 13 | C 14 | D = C + 1 15 | F = Class(5) 16 | //G is not enum 17 | G = H + 10 18 | //H is not enum 19 | H = 10 20 | //I is not enum 21 | I = int(F + 2) 22 | ) 23 | 24 | const J = 1 << uint16(I) 25 | 26 | type Mask int 27 | 28 | const ( 29 | Mask1 Mask = 0x02 << iota >> 1 // Mask1 30 | Mask2 /* Mask2 */ 31 | Mask3 // Mask3 32 | Mask4 // Mask4 33 | Mask5 = Mask(A + B) 34 | ) 35 | 36 | type Type string 37 | 38 | const ( 39 | Teacher Type = "teacher" // teacher 40 | Student Type = "student" /* student */ 41 | Other Type = "Other" // Other 42 | Unknown = "Unknown" 43 | OtherUnknown = string(Other + Unknown) 44 | ) 45 | 46 | type Sex rune 47 | 48 | const ( 49 | Male Sex = 'M' 50 | Female = 'F' 51 | ) 52 | 53 | type Person struct { 54 | Name string 55 | Class Class 56 | Mask Mask 57 | Type Type 58 | } 59 | 60 | type PersonWithArrayEnum struct { 61 | Name string 62 | Class []Class 63 | Mask []Mask 64 | Type Type 65 | } 66 | -------------------------------------------------------------------------------- /testdata/error/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | . "github.com/swaggo/swag/testdata/error/errors" 7 | _ "github.com/swaggo/swag/testdata/error/web" 8 | ) 9 | 10 | // Upload do something 11 | // @Summary Upload file 12 | // @Description Upload file 13 | // @ID file.upload 14 | // @Accept multipart/form-data 15 | // @Produce json 16 | // @Param file formData file true "this is a test file" 17 | // @Success 200 {string} string "ok" 18 | // @Failure 400 {object} web.CrossErrors "Abort !!" 19 | // @Router /file/upload [post] 20 | func Upload(w http.ResponseWriter, r *http.Request) { 21 | //write your code 22 | _ = Errors{} 23 | } 24 | -------------------------------------------------------------------------------- /testdata/error/errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | // CustomInterface some interface 4 | type CustomInterface interface { 5 | Error() string 6 | } 7 | 8 | // Errors errors and interfaces 9 | type Errors struct { 10 | Error error 11 | ErrorInterface CustomInterface 12 | Interface interface{} 13 | Any any 14 | } 15 | -------------------------------------------------------------------------------- /testdata/error/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server Petstore server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "host": "petstore.swagger.io", 19 | "basePath": "/v2", 20 | "paths": { 21 | "/file/upload": { 22 | "post": { 23 | "description": "Upload file", 24 | "consumes": [ 25 | "multipart/form-data" 26 | ], 27 | "produces": [ 28 | "application/json" 29 | ], 30 | "summary": "Upload file", 31 | "operationId": "file.upload", 32 | "parameters": [ 33 | { 34 | "type": "file", 35 | "description": "this is a test file", 36 | "name": "file", 37 | "in": "formData", 38 | "required": true 39 | } 40 | ], 41 | "responses": { 42 | "200": { 43 | "description": "ok", 44 | "schema": { 45 | "type": "string" 46 | } 47 | }, 48 | "400": { 49 | "description": "Abort !!", 50 | "schema": { 51 | "$ref": "#/definitions/web.CrossErrors" 52 | } 53 | } 54 | } 55 | } 56 | } 57 | }, 58 | "definitions": { 59 | "web.CrossErrors": { 60 | "type": "object", 61 | "properties": { 62 | "any": {}, 63 | "error": {}, 64 | "errorInterface": {}, 65 | "interface": {} 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /testdata/error/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/error/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | func main() { 25 | http.HandleFunc("/testapi/upload", api.Upload) 26 | http.ListenAndServe(":8080", nil) 27 | } 28 | -------------------------------------------------------------------------------- /testdata/error/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "github.com/swaggo/swag/testdata/error/errors" 5 | ) 6 | 7 | type CrossErrors errors.Errors 8 | -------------------------------------------------------------------------------- /testdata/extensionsFail1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description This is a sample server Petstore server. 6 | // @description It has a lot of beautiful features. 7 | // @termsOfService http://swagger.io/terms/ 8 | 9 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 10 | // @tokenUrl https://example.com/oauth/token 11 | // @authorizationurl https://example.com/oauth/authorize 12 | // @scope.admin Grants read and write access to administrative information 13 | 14 | // @x-google-endpoints ["name":"name.endpoints.environment.cloud.goog","allowCors":true}] 15 | -------------------------------------------------------------------------------- /testdata/extensionsFail2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description This is a sample server Petstore server. 6 | // @description It has a lot of beautiful features. 7 | // @termsOfService http://swagger.io/terms/ 8 | 9 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 10 | // @tokenUrl https://example.com/oauth/token 11 | // @authorizationurl https://example.com/oauth/authorize 12 | // @scope.admin Grants read and write access to administrative information 13 | 14 | // @x-google-endpoints 15 | -------------------------------------------------------------------------------- /testdata/external_models/external/model.go: -------------------------------------------------------------------------------- 1 | package external 2 | 3 | import "github.com/urfave/cli/v2" 4 | 5 | type MyError struct { 6 | cli.Author 7 | } 8 | -------------------------------------------------------------------------------- /testdata/external_models/main/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // GetExternalModels example 8 | // @Summary parse external models 9 | // @Description get string by ID 10 | // @ID get_external_models 11 | // @Accept json 12 | // @Produce json 13 | // @Success 200 {string} string "ok" 14 | // @Failure 400 {object} http.Header "from internal pkg" 15 | // @Router /testapi/external_models [get] 16 | func GetExternalModels(w http.ResponseWriter, r *http.Request) { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /testdata/external_models/main/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "Parse external models.", 5 | "title": "Swagger Example API", 6 | "contact": {}, 7 | "version": "1.0" 8 | }, 9 | "basePath": "/v1", 10 | "paths": { 11 | "/testapi/external_models": { 12 | "get": { 13 | "description": "get string by ID", 14 | "consumes": [ 15 | "application/json" 16 | ], 17 | "produces": [ 18 | "application/json" 19 | ], 20 | "summary": "parse external models", 21 | "operationId": "get_external_models", 22 | "responses": { 23 | "200": { 24 | "description": "ok", 25 | "schema": { 26 | "type": "string" 27 | } 28 | }, 29 | "400": { 30 | "description": "from internal pkg", 31 | "schema": { 32 | "$ref": "#/definitions/http.Header" 33 | } 34 | } 35 | } 36 | } 37 | } 38 | }, 39 | "definitions": { 40 | "http.Header": { 41 | "type": "object", 42 | "additionalProperties": { 43 | "type": "array", 44 | "items": { 45 | "type": "string" 46 | } 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /testdata/external_models/main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description Parse external models. 6 | // @BasePath /v1 7 | func main() { 8 | } 9 | -------------------------------------------------------------------------------- /testdata/fixes-432/a/a.go: -------------------------------------------------------------------------------- 1 | package a 2 | -------------------------------------------------------------------------------- /testdata/fixes-432/b/b.go: -------------------------------------------------------------------------------- 1 | package b 2 | -------------------------------------------------------------------------------- /testdata/fixes-432/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /testdata/format_dst/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/simple/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | // @securityDefinitions.basic BasicAuth 25 | 26 | // @securityDefinitions.apikey ApiKeyAuth 27 | // @in header 28 | // @name Authorization 29 | 30 | // @securitydefinitions.oauth2.application OAuth2Application 31 | // @tokenUrl https://example.com/oauth/token 32 | // @scope.write Grants write access 33 | // @scope.admin Grants read and write access to administrative information 34 | 35 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 36 | // @authorizationurl https://example.com/oauth/authorize 37 | // @scope.write Grants write access 38 | // @scope.admin Grants read and write access to administrative information 39 | 40 | // @securitydefinitions.oauth2.password OAuth2Password 41 | // @tokenUrl https://example.com/oauth/token 42 | // @scope.read Grants read access 43 | // @scope.write Grants write access 44 | // @scope.admin Grants read and write access to administrative information 45 | 46 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 47 | // @tokenUrl https://example.com/oauth/token 48 | // @authorizationurl https://example.com/oauth/authorize 49 | // @scope.admin Grants read and write access to administrative information 50 | func main() { 51 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 52 | http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByString) 53 | http.HandleFunc("/testapi/upload", api.Upload) 54 | http.ListenAndServe(":8080", nil) 55 | } 56 | -------------------------------------------------------------------------------- /testdata/format_empty/empty.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // nothing 4 | -------------------------------------------------------------------------------- /testdata/format_src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/simple/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | // @securityDefinitions.basic BasicAuth 25 | 26 | // @securityDefinitions.apikey ApiKeyAuth 27 | // @in header 28 | // @name Authorization 29 | 30 | // @securitydefinitions.oauth2.application OAuth2Application 31 | // @tokenUrl https://example.com/oauth/token 32 | // @scope.write Grants write access 33 | // @scope.admin Grants read and write access to administrative information 34 | 35 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 36 | // @authorizationurl https://example.com/oauth/authorize 37 | // @scope.write Grants write access 38 | // @scope.admin Grants read and write access to administrative information 39 | 40 | // @securitydefinitions.oauth2.password OAuth2Password 41 | // @tokenUrl https://example.com/oauth/token 42 | // @scope.read Grants read access 43 | // @scope.write Grants write access 44 | // @scope.admin Grants read and write access to administrative information 45 | 46 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 47 | // @tokenUrl https://example.com/oauth/token 48 | // @authorizationurl https://example.com/oauth/authorize 49 | // @scope.admin Grants read and write access to administrative information 50 | func main() { 51 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 52 | http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByString) 53 | http.HandleFunc("/testapi/upload", api.Upload) 54 | http.ListenAndServe(":8080", nil) 55 | } 56 | -------------------------------------------------------------------------------- /testdata/format_test/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/simple/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | // @securityDefinitions.basic BasicAuth 25 | 26 | // @securityDefinitions.apikey ApiKeyAuth 27 | // @in header 28 | // @name Authorization 29 | 30 | // @securitydefinitions.oauth2.application OAuth2Application 31 | // @tokenUrl https://example.com/oauth/token 32 | // @scope.write Grants write access 33 | // @scope.admin Grants read and write access to administrative information 34 | 35 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 36 | // @authorizationurl https://example.com/oauth/authorize 37 | // @scope.write Grants write access 38 | // @scope.admin Grants read and write access to administrative information 39 | 40 | // @securitydefinitions.oauth2.password OAuth2Password 41 | // @tokenUrl https://example.com/oauth/token 42 | // @scope.read Grants read access 43 | // @scope.write Grants write access 44 | // @scope.admin Grants read and write access to administrative information 45 | 46 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 47 | // @tokenUrl https://example.com/oauth/token 48 | // @authorizationurl https://example.com/oauth/authorize 49 | // @scope.admin Grants read and write access to administrative information 50 | func main() { 51 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 52 | http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByString) 53 | http.HandleFunc("/testapi/upload", api.Upload) 54 | http.ListenAndServe(":8080", nil) 55 | } 56 | -------------------------------------------------------------------------------- /testdata/generics_arrays/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_arrays/types" 7 | "github.com/swaggo/swag/testdata/generics_arrays/web" 8 | ) 9 | 10 | // @Summary List Posts 11 | // @Description Get All of the Posts 12 | // @Accept json 13 | // @Produce json 14 | // @Param data body web.GenericListBody[types.Post] true "Some ID" 15 | // @Success 200 {object} web.GenericListResponse[types.Post] 16 | // @Success 222 {object} web.GenericListResponseMulti[types.Post, types.Post] 17 | // @Router /posts [get] 18 | func GetPosts(w http.ResponseWriter, r *http.Request) { 19 | _ = web.GenericListResponseMulti[types.Post, types.Post]{} 20 | } 21 | 22 | // @Summary Add new pets to the store 23 | // @Description get string by ID 24 | // @Accept json 25 | // @Produce json 26 | // @Param data body web.GenericListBodyMulti[types.Post, types.Post] true "Some ID" 27 | // @Success 200 {object} web.GenericListResponse[types.Post] 28 | // @Success 222 {object} web.GenericListResponseMulti[types.Post, types.Post] 29 | // @Router /posts-multi [get] 30 | func GetPostMulti(w http.ResponseWriter, r *http.Request) { 31 | //write your code 32 | _ = web.GenericListResponseMulti[types.Post, types.Post]{} 33 | } 34 | 35 | // @Summary Add new pets to the store 36 | // @Description get string by ID 37 | // @Accept json 38 | // @Produce json 39 | // @Param data body web.GenericListBodyMulti[types.Post, []types.Post] true "Some ID" 40 | // @Success 200 {object} web.GenericListResponse[[]types.Post] 41 | // @Success 222 {object} web.GenericListResponseMulti[types.Post, []types.Post] 42 | // @Router /posts-multis [get] 43 | func GetPostArray(w http.ResponseWriter, r *http.Request) { 44 | //write your code 45 | _ = web.GenericListResponseMulti[types.Post, []types.Post]{} 46 | } 47 | -------------------------------------------------------------------------------- /testdata/generics_arrays/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_arrays/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @host localhost:4000 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/posts/", api.GetPosts) 16 | http.HandleFunc("/posts-multi/", api.GetPostMulti) 17 | http.HandleFunc("/posts-multis/", api.GetPostArray) 18 | http.ListenAndServe(":8080", nil) 19 | } 20 | -------------------------------------------------------------------------------- /testdata/generics_arrays/types/post.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type APIBase struct { 4 | APIUrl string `json:"@uri,omitempty"` 5 | ID int `json:"id" example:"1" format:"int64"` 6 | } 7 | 8 | type Post struct { 9 | APIBase 10 | // Post name 11 | Name string `json:"name" example:"poti"` 12 | // Post data 13 | Data struct { 14 | // Post tag 15 | Tag []string `json:"name"` 16 | } `json:"data"` 17 | } 18 | -------------------------------------------------------------------------------- /testdata/generics_arrays/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type GenericListBody[T any] struct { 8 | Data []T 9 | } 10 | 11 | type GenericListBodyMulti[T any, X any] struct { 12 | Data []T 13 | Meta []X 14 | } 15 | 16 | // GenericListResponse[T] 17 | // @Description Some Generic List Response 18 | type GenericListResponse[T any] struct { 19 | // Items from the list response 20 | Items []T 21 | // Status of some other stuff 22 | Status string 23 | } 24 | 25 | // GenericListResponseMulti[T, X] 26 | // @Description this contains a few things 27 | type GenericListResponseMulti[T any, X any] struct { 28 | // ItemsOne is the first thing 29 | ItemsOne []T 30 | // ItemsTwo is the second thing 31 | ItemsTwo []X 32 | 33 | // Status of the things 34 | Status string 35 | } 36 | 37 | // APIError 38 | // @Description API error 39 | // @Description with information about it 40 | // Other some summary 41 | type APIError struct { 42 | // Error an Api error 43 | Error string // Error this is Line comment 44 | // Error `number` tick comment 45 | ErrorNo int64 46 | ErrorCtx string // Error `context` tick comment 47 | CreatedAt time.Time // Error time 48 | } 49 | -------------------------------------------------------------------------------- /testdata/generics_basic/.swaggo: -------------------------------------------------------------------------------- 1 | replace types.Field[string] string 2 | replace types.DoubleField[string,string] []string 3 | replace types.TrippleField[string,string] [][]string -------------------------------------------------------------------------------- /testdata/generics_basic/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_basic/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @host localhost:4000 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/posts/", api.GetPost) 16 | http.HandleFunc("/posts-multi/", api.GetPostMulti) 17 | http.HandleFunc("/posts-multis/", api.GetPostArray) 18 | http.ListenAndServe(":8080", nil) 19 | } 20 | -------------------------------------------------------------------------------- /testdata/generics_basic/types/post.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type APIBase struct { 4 | APIUrl string `json:"@uri,omitempty"` 5 | ID int `json:"id" example:"1" format:"int64"` 6 | } 7 | 8 | type Post struct { 9 | APIBase 10 | ID int `json:"id" example:"1" format:"int64"` 11 | // Post name 12 | Name string `json:"name" example:"poti"` 13 | // Post data 14 | Data struct { 15 | // Post tag 16 | Tag []string `json:"name"` 17 | } `json:"data"` 18 | } 19 | -------------------------------------------------------------------------------- /testdata/generics_basic/types/string.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type Field[T any] struct { 4 | Value T 5 | } 6 | 7 | type DoubleField[T1 any, T2 any] struct { 8 | Value1 T1 9 | Value2 T2 10 | } 11 | 12 | type TrippleField[T1 any, T2 any] struct { 13 | Value1 T1 14 | Value2 T2 15 | } 16 | 17 | type ArrayField[T any] []T 18 | type MapField[K comparable, V any] map[K]V 19 | type MapFieldValue struct { 20 | S string 21 | F float64 22 | } 23 | type MapFieldNestedStruct[K comparable] map[K]MapFieldValue 24 | 25 | type Hello struct { 26 | MyStringField1 Field[*string] `json:"myStringField1"` 27 | MyStringField2 Field[string] `json:"myStringField2"` 28 | MyArrayField DoubleField[*string, string] `json:"myNewField"` 29 | MyArrayDepthField TrippleField[*string, string] `json:"myNewArrayField"` 30 | ArrayField ArrayField[string] `json:"arrayField"` 31 | MapField MapField[string, float64] `json:"mapField"` 32 | OriginArrayField []string `json:"originArrayField"` 33 | OriginMapField map[string]float64 `json:"originMapField"` 34 | MapFieldNestedStruct MapFieldNestedStruct[string] `json:"mapFieldNestedStruct"` 35 | } 36 | -------------------------------------------------------------------------------- /testdata/generics_basic/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type GenericBody[T any] struct { 8 | Data T 9 | } 10 | 11 | type GenericBodyMulti[T any, X any] struct { 12 | Data T 13 | Meta X 14 | } 15 | 16 | type GenericResponse[T any] struct { 17 | Data T 18 | 19 | Status string 20 | } 21 | 22 | type GenericResponseMulti[T any, X any] struct { 23 | Data T 24 | Meta X 25 | 26 | Status string 27 | } 28 | 29 | // APIError 30 | // @Description API error 31 | // @Description with information about it 32 | // Other some summary 33 | type APIError struct { 34 | // Error an Api error 35 | Error string // Error this is Line comment 36 | // Error `number` tick comment 37 | ErrorNo int64 38 | ErrorCtx string // Error `context` tick comment 39 | CreatedAt time.Time // Error time 40 | } 41 | -------------------------------------------------------------------------------- /testdata/generics_function_scoped/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_function_scoped/types" 7 | ) 8 | 9 | // @Summary Generic Response 10 | // @Produce json 11 | // @Success 200 {object} types.GenericResponse[api.GetGeneric.User] 12 | // @Success 201 {object} types.GenericResponse[api.GetGeneric.Post] 13 | // @Router / [get] 14 | func GetGeneric(w http.ResponseWriter, r *http.Request) { 15 | type User struct { 16 | Username int `json:"username"` 17 | Email string `json:"email"` 18 | } 19 | type Post struct { 20 | Slug int `json:"slug"` 21 | Title string `json:"title"` 22 | } 23 | 24 | _ = types.GenericResponse[any]{} 25 | } 26 | 27 | // @Summary Generic Response With Custom Type Names 28 | // @Produce json 29 | // @Success 200 {object} types.GenericResponse[api.GetGenericRenamed.User] 30 | // @Success 201 {object} types.GenericResponse[api.GetGenericRenamed.Post] 31 | // @Router /renamed [get] 32 | func GetGenericRenamed(w http.ResponseWriter, r *http.Request) { 33 | type User struct { 34 | Username int `json:"username"` 35 | Email string `json:"email"` 36 | } // @Name RenamedUserData 37 | type Post struct { 38 | Slug int `json:"slug"` 39 | Title string `json:"title"` 40 | } // @Name RenamedPostData 41 | 42 | _ = types.GenericResponse[any]{} 43 | } 44 | 45 | // @Summary Multiple Generic Response 46 | // @Produce json 47 | // @Success 200 {object} types.GenericMultiResponse[api.GetGenericMulti.MyStructA, api.GetGenericMulti.MyStructB] 48 | // @Success 201 {object} types.GenericMultiResponse[api.GetGenericMulti.MyStructB, api.GetGenericMulti.MyStructA] 49 | // @Router /multi [get] 50 | func GetGenericMulti(w http.ResponseWriter, r *http.Request) { 51 | type MyStructA struct { 52 | SomeFieldA string `json:"some_field_a"` 53 | } 54 | type MyStructB struct { 55 | SomeFieldB string `json:"some_field_b"` 56 | } 57 | 58 | _ = types.GenericMultiResponse[any, any]{} 59 | } 60 | 61 | // @Summary Multiple Generic Response With Custom Type Names 62 | // @Produce json 63 | // @Success 200 {object} types.GenericMultiResponse[api.GetGenericMultiRenamed.MyStructA, api.GetGenericMultiRenamed.MyStructB] 64 | // @Success 201 {object} types.GenericMultiResponse[api.GetGenericMultiRenamed.MyStructB, api.GetGenericMultiRenamed.MyStructA] 65 | // @Router /multi-renamed [get] 66 | func GetGenericMultiRenamed(w http.ResponseWriter, r *http.Request) { 67 | type MyStructA struct { 68 | SomeFieldA string `json:"some_field_a"` 69 | } // @Name NameForMyStructA 70 | type MyStructB struct { 71 | SomeFieldB string `json:"some_field_b"` 72 | } // @Name NameForMyStructB 73 | 74 | _ = types.GenericMultiResponse[any, any]{} 75 | } 76 | -------------------------------------------------------------------------------- /testdata/generics_function_scoped/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_function_scoped/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server. 12 | // @host localhost:8080 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/", api.GetGeneric) 16 | http.HandleFunc("/renamed", api.GetGenericRenamed) 17 | http.HandleFunc("/multi", api.GetGenericMulti) 18 | http.HandleFunc("/multi-renamed", api.GetGenericMulti) 19 | http.ListenAndServe(":8080", nil) 20 | } 21 | -------------------------------------------------------------------------------- /testdata/generics_function_scoped/types/response.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type GenericResponse[T any] struct { 4 | Status string `json:"status"` 5 | Data T `json:"data"` 6 | } 7 | 8 | type GenericMultiResponse[T any, X any] struct { 9 | Status string `json:"status"` 10 | DataT T `json:"data_t"` 11 | DataX X `json:"data_x"` 12 | } 13 | -------------------------------------------------------------------------------- /testdata/generics_multi_level_nesting/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // GetPosts 8 | // @Summary Test Generics with multi level nesting 9 | // @Description Test one of the edge cases found in generics 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} web.TestResponse 13 | // @Router /use-struct-and-generics-with-multi-level-nesting [get] 14 | func GetPosts(w http.ResponseWriter, r *http.Request) { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /testdata/generics_multi_level_nesting/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_nested_my_version/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @host localhost:4000 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/posts/", api.GetPosts) 16 | http.ListenAndServe(":8080", nil) 17 | } 18 | -------------------------------------------------------------------------------- /testdata/generics_multi_level_nesting/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | type TestResponse struct { 8 | Field1 Entity[int64] `json:"field_1"` 9 | Field2 Entity[float64] `json:"field_2"` 10 | } 11 | 12 | type Entity[T int64 | float64] struct { 13 | LineWithFixType EmptyArray[DataPoint[float64]] `json:"line_with_fix_type"` 14 | LineWithGenericType EmptyArray[DataPoint[T]] `json:"line_with_generic_type"` 15 | MultipleLines MultipleLines[T] `json:"multiple_lines"` 16 | } 17 | 18 | type DataPoint[T int64 | float64] struct { 19 | Value T `json:"value"` 20 | Timestamp int64 `json:"timestamp"` 21 | } 22 | 23 | // EmptyArray will show [] instead of nil. 24 | type EmptyArray[T any] []T 25 | 26 | func (arr EmptyArray[T]) MarshalJSON() ([]byte, error) { 27 | if arr != nil { 28 | return json.Marshal([]T(arr)) 29 | } 30 | 31 | return json.Marshal(make([]T, 0)) 32 | } 33 | 34 | type MultipleLines[T int64 | float64] []NamedLineData[T] 35 | 36 | type NamedLineData[T int64 | float64] struct { 37 | Name string `json:"name"` 38 | Data EmptyArray[DataPoint[T]] `json:"data"` 39 | } 40 | -------------------------------------------------------------------------------- /testdata/generics_names/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_names/types" 7 | "github.com/swaggo/swag/testdata/generics_names/web" 8 | ) 9 | 10 | // @Summary Add a new pet to the store 11 | // @Description get string by ID 12 | // @Accept json 13 | // @Produce json 14 | // @Param data body web.GenericBody[types.Post] true "Some ID" 15 | // @Success 200 {object} web.GenericResponse[types.Post] 16 | // @Success 222 {object} web.GenericResponseMulti[types.Post, types.Post] 17 | // @Failure 400 {object} web.APIError "We need ID!!" 18 | // @Failure 404 {object} web.APIError "Can not find ID" 19 | // @Router /posts/ [post] 20 | func GetPost(w http.ResponseWriter, r *http.Request) { 21 | //write your code 22 | _ = web.GenericResponse[types.Post]{} 23 | } 24 | 25 | // @Summary Add new pets to the store 26 | // @Description get string by ID 27 | // @Accept json 28 | // @Produce json 29 | // @Param data body web.GenericBodyMulti[types.Post, types.Post] true "Some ID" 30 | // @Success 200 {object} web.GenericResponse[types.Post] 31 | // @Success 222 {object} web.GenericResponseMulti[types.Post, types.Post] 32 | // @Router /posts-multi/ [post] 33 | func GetPostMulti(w http.ResponseWriter, r *http.Request) { 34 | //write your code 35 | _ = web.GenericResponse[types.Post]{} 36 | } 37 | 38 | // @Summary Add new pets to the store 39 | // @Description get string by ID 40 | // @Accept json 41 | // @Produce json 42 | // @Param data body web.GenericBodyMulti[[]types.Post, [][]types.Post] true "Some ID" 43 | // @Success 200 {object} web.GenericResponse[[]types.Post] 44 | // @Success 222 {object} web.GenericResponseMulti[[]types.Post, [][]types.Post] 45 | // @Router /posts-multis/ [post] 46 | func GetPostArray(w http.ResponseWriter, r *http.Request) { 47 | //write your code 48 | _ = web.GenericResponse[types.Post]{} 49 | } 50 | -------------------------------------------------------------------------------- /testdata/generics_names/api/api_alias_pkg.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | mytypes "github.com/swaggo/swag/testdata/generics_names/types" 7 | myweb "github.com/swaggo/swag/testdata/generics_names/web" 8 | ) 9 | 10 | // @Summary Add a new pet to the store 11 | // @Description get string by ID 12 | // @Accept json 13 | // @Produce json 14 | // @Success 200 {object} myweb.AliasPkgGenericResponse[mytypes.Post] 15 | // @Router /posts/aliaspkg [post] 16 | func GetPostFromAliasPkg(w http.ResponseWriter, r *http.Request) { 17 | //write your code 18 | _ = myweb.AliasPkgGenericResponse[mytypes.Post]{} 19 | } 20 | -------------------------------------------------------------------------------- /testdata/generics_names/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_names/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @host localhost:4000 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/posts/", api.GetPost) 16 | http.HandleFunc("/posts-multi/", api.GetPostMulti) 17 | http.HandleFunc("/posts-multis/", api.GetPostArray) 18 | http.ListenAndServe(":8080", nil) 19 | } 20 | -------------------------------------------------------------------------------- /testdata/generics_names/types/post.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type APIBase struct { 4 | APIUrl string `json:"@uri,omitempty"` 5 | ID int `json:"id" example:"1" format:"int64"` 6 | } 7 | 8 | type Post struct { 9 | APIBase 10 | // Post name 11 | Name string `json:"name" example:"poti"` 12 | // Post data 13 | Data struct { 14 | // Post tag 15 | Tag []string `json:"name"` 16 | } `json:"data"` 17 | } // @name Post 18 | -------------------------------------------------------------------------------- /testdata/generics_names/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type GenericBody[T any] struct { 8 | Data T 9 | } // @name Body 10 | 11 | type GenericBodyMulti[T any, X any] struct { 12 | Data T 13 | Meta X 14 | } // @name MultiBody 15 | 16 | type GenericResponse[T any] struct { 17 | Data T 18 | 19 | Status string 20 | } // @name Response 21 | 22 | type GenericResponseMulti[T any, X any] struct { 23 | Data T 24 | Meta X 25 | 26 | Status string 27 | } // @name MultiResponse 28 | 29 | // APIError 30 | // @Description API error 31 | // @Description with information about it 32 | // Other some summary 33 | type APIError struct { 34 | // Error an Api error 35 | Error string // Error this is Line comment 36 | // Error `number` tick comment 37 | ErrorNo int64 38 | ErrorCtx string // Error `context` tick comment 39 | CreatedAt time.Time // Error time 40 | } 41 | 42 | type AliasPkgGenericResponse[T any] struct { 43 | Data T 44 | 45 | Status string 46 | } 47 | -------------------------------------------------------------------------------- /testdata/generics_nested/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_nested/types" 7 | "github.com/swaggo/swag/testdata/generics_nested/web" 8 | ) 9 | 10 | // @Summary List Posts 11 | // @Description Get All of the Posts 12 | // @Accept json 13 | // @Produce json 14 | // @Param data body web.GenericNestedBody[web.GenericInnerType[types.Post]] true "Some ID" 15 | // @Success 200 {object} web.GenericNestedResponse[types.Post] 16 | // @Success 201 {object} web.GenericNestedResponse[web.GenericInnerType[types.Post]] 17 | // @Success 202 {object} web.GenericNestedResponseMulti[types.Post, web.GenericInnerMultiType[types.Post, types.Post]] 18 | // @Success 203 {object} web.GenericNestedResponseMulti[types.Post, web.GenericInnerMultiType[types.Post, web.GenericInnerType[types.Post]]] 19 | // @Success 222 {object} web.GenericNestedResponseMulti[web.GenericInnerType[types.Post], types.Post] 20 | // @Router /posts [get] 21 | func GetPosts(w http.ResponseWriter, r *http.Request) { 22 | _ = web.GenericNestedResponse[types.Post]{} 23 | } 24 | 25 | // @Summary List Posts 26 | // @Description Get All of the Posts 27 | // @Accept json 28 | // @Produce json 29 | // @Param data body web.GenericNestedBody[web.GenericInnerType[[]types.Post]] true "Some ID" 30 | // @Success 200 {object} web.GenericNestedResponse[[]types.Post] 31 | // @Success 201 {object} web.GenericNestedResponse[[]web.GenericInnerType[types.Post]] 32 | // @Success 202 {object} web.GenericNestedResponse[[]web.GenericInnerType[[]types.Post]] 33 | // @Success 203 {object} web.GenericNestedResponseMulti[[]types.Post, web.GenericInnerMultiType[[]types.Post, types.Post]] 34 | // @Success 204 {object} web.GenericNestedResponseMulti[[]types.Post, []web.GenericInnerMultiType[[]types.Post, types.Post]] 35 | // @Success 205 {object} web.GenericNestedResponseMulti[types.Post, web.GenericInnerMultiType[types.Post, []web.GenericInnerType[[][]types.Post]]] 36 | // @Success 222 {object} web.GenericNestedResponseMulti[web.GenericInnerType[[]types.Post], []types.Post] 37 | // @Router /posts-multis/ [get] 38 | func GetPostArray(w http.ResponseWriter, r *http.Request) { 39 | _ = web.GenericNestedResponse[types.Post]{} 40 | } 41 | 42 | // @Summary List Posts 43 | // @Description Get All of the Posts 44 | // @Accept json 45 | // @Produce json 46 | // @Success 200 {object} web.GenericNodeThree[string] 47 | // @Router /posts-self-nested-struct/ [get] 48 | func GetPostSelfNestStruct(w http.ResponseWriter, r *http.Request) { 49 | 50 | } 51 | -------------------------------------------------------------------------------- /testdata/generics_nested/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_nested/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @host localhost:4000 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/posts/", api.GetPosts) 16 | http.ListenAndServe(":8080", nil) 17 | } 18 | -------------------------------------------------------------------------------- /testdata/generics_nested/types/post.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type APIBase struct { 4 | APIUrl string `json:"@uri,omitempty"` 5 | ID int `json:"id" example:"1" format:"int64"` 6 | } 7 | 8 | type Post struct { 9 | APIBase 10 | // Post name 11 | Name string `json:"name" example:"poti"` 12 | // Post data 13 | Data struct { 14 | // Post tag 15 | Tag []string `json:"name"` 16 | } `json:"data"` 17 | } 18 | -------------------------------------------------------------------------------- /testdata/generics_nested/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // GenericNestedBody[T] 8 | // @Description Some Generic Body 9 | type GenericNestedBody[T any] struct { 10 | // Items from the list response 11 | Items T 12 | // Status of some other stuff 13 | Status string 14 | } 15 | 16 | // GenericInnerType[T] 17 | // @Description Some Generic Body 18 | type GenericInnerType[T any] struct { 19 | // Items from the list response 20 | Items T 21 | } 22 | 23 | // GenericInnerMultiType[T, X] 24 | // @Description Some Generic Body 25 | type GenericInnerMultiType[T any, X any] struct { 26 | // ItemsOne is the first thing 27 | ItemOne T 28 | // ItemsTwo is the second thing 29 | ItemsTwo []X 30 | } 31 | 32 | // GenericNestedResponse[T] 33 | // @Description Some Generic List Response 34 | type GenericNestedResponse[T any] struct { 35 | // Items from the list response 36 | Items []T 37 | // Status of some other stuff 38 | Status string 39 | } 40 | 41 | // GenericNestedResponseMulti[T, X] 42 | // @Description this contains a few things 43 | type GenericNestedResponseMulti[T any, X any] struct { 44 | // ItemsOne is the first thing 45 | ItemOne T 46 | // ItemsTwo is the second thing 47 | ItemsTwo []X 48 | 49 | // Status of the things 50 | Status string 51 | } 52 | 53 | // APIError 54 | // @Description API error 55 | // @Description with information about it 56 | // Other some summary 57 | type APIError struct { 58 | // Error an Api error 59 | Error string // Error this is Line comment 60 | // Error `number` tick comment 61 | ErrorNo int64 62 | ErrorCtx string // Error `context` tick comment 63 | CreatedAt time.Time // Error time 64 | } 65 | 66 | type GenericNodeThree[T any] struct { 67 | CurrentData []T `json:"current"` 68 | Next []*GenericNodeThree[T] `json:"next"` 69 | } 70 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/external/external1/external.go: -------------------------------------------------------------------------------- 1 | package external1 2 | 3 | type Customer struct { 4 | Name string 5 | Age int 6 | } 7 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/external/external2/external.go: -------------------------------------------------------------------------------- 1 | package external2 2 | 3 | type Customer struct { 4 | Name string 5 | Age int 6 | } 7 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/external/external3/external.go: -------------------------------------------------------------------------------- 1 | package external3 2 | 3 | type Customer struct { 4 | Name string 5 | Age int 6 | } 7 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/external/external4/external.go: -------------------------------------------------------------------------------- 1 | package external4 2 | 3 | type Customer struct { 4 | Name string 5 | Age int 6 | } 7 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api1.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | myv1 "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 5 | ) 6 | 7 | // @Summary Create movie 8 | // @Description Create a new movie production 9 | // @Accept json 10 | // @Produce json 11 | // @Success 200 {object} myv1.ListResult[myv1.ProductDto] "" 12 | // @Router /api01 [post] 13 | func CreateMovie01() { 14 | _ = myv1.ListResult[myv1.ProductDto]{} 15 | } 16 | 17 | // @Summary Create movie 18 | // @Description Create a new movie production 19 | // @Accept json 20 | // @Produce json 21 | // @Success 200 {object} myv1.RenamedListResult[myv1.RenamedProductDto] "" 22 | // @Router /api02 [post] 23 | func CreateMovie02() { 24 | _ = myv1.ListResult[myv1.ProductDto]{} 25 | } 26 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api2.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | myv1 "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 5 | myv2 "github.com/swaggo/swag/testdata/generics_package_alias/internal/path2/v1" 6 | ) 7 | 8 | // @Summary Create movie 9 | // @Description Create a new movie production 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} myv2.ListResult[myv2.ProductDto] "" 13 | // @Router /api03 [post] 14 | func CreateMovie03() { 15 | _ = myv2.ListResult[myv2.ProductDto]{} 16 | } 17 | 18 | // @Summary Create movie 19 | // @Description Create a new movie production 20 | // @Accept json 21 | // @Produce json 22 | // @Success 200 {object} myv2.RenamedListResult[myv2.RenamedProductDto] "" 23 | // @Router /api04 [post] 24 | func CreateMovie04() { 25 | _ = myv2.ListResult[myv2.ProductDto]{} 26 | } 27 | 28 | // @Summary Create movie 29 | // @Description Create a new movie production 30 | // @Accept json 31 | // @Produce json 32 | // @Success 200 {object} myv1.ListResult[myv2.ProductDto] "" 33 | // @Router /api05 [post] 34 | func CreateMovie05() { 35 | _ = myv1.ListResult[myv2.ProductDto]{} 36 | } 37 | 38 | // @Summary Create movie 39 | // @Description Create a new movie production 40 | // @Accept json 41 | // @Produce json 42 | // @Success 200 {object} myv1.RenamedListResult[myv2.RenamedProductDto] "" 43 | // @Router /api06 [post] 44 | func CreateMovie06() { 45 | _ = myv1.ListResult[myv2.ProductDto]{} 46 | } 47 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api3.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | _ "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 5 | . "github.com/swaggo/swag/testdata/generics_package_alias/internal/path2/v1" 6 | ) 7 | 8 | // @Summary Create movie 9 | // @Description models imported from an unnamed package 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} v1.ListResult[v1.ProductDto] "" 13 | // @Router /api07 [post] 14 | func CreateMovie07() { 15 | var _ ProductDto 16 | } 17 | 18 | // @Summary Create movie 19 | // @Description models imported from an unnamed package 20 | // @Accept json 21 | // @Produce json 22 | // @Success 200 {object} ListResult[ProductDto] "" 23 | // @Router /api08 [post] 24 | func CreateMovie08() { 25 | var _ ProductDto 26 | } 27 | 28 | // @Summary Create movie 29 | // @Description models imported from an unnamed package 30 | // @Accept json 31 | // @Produce json 32 | // @Success 200 {object} ListResult[v1.ProductDto] "" 33 | // @Router /api09 [post] 34 | func CreateMovie09() { 35 | var _ ProductDto 36 | } 37 | 38 | // @Summary Create movie 39 | // @Description models imported from an unnamed package 40 | // @Accept json 41 | // @Produce json 42 | // @Success 200 {object} v1.ListResult[ProductDto] "" 43 | // @Router /api10 [post] 44 | func CreateMovie10() { 45 | var _ ProductDto 46 | } 47 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api4.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/swaggo/swag/testdata/generics_package_alias/external/external1" 5 | _ "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 6 | ) 7 | 8 | // @Summary Create movie 9 | // @Description models imported from an external package 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} v1.ListResult[external1.Customer] "" 13 | // @Router /api11 [post] 14 | func CreateMovie11() { 15 | var _ external1.Customer 16 | } 17 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api5.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | myexternal "github.com/swaggo/swag/testdata/generics_package_alias/external/external2" 5 | _ "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 6 | ) 7 | 8 | // @Summary Create movie 9 | // @Description models imported from a named external package 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} v1.ListResult[myexternal.Customer] "" 13 | // @Router /api12 [post] 14 | func CreateMovie12() { 15 | var _ myexternal.Customer 16 | } 17 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api6.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | . "github.com/swaggo/swag/testdata/generics_package_alias/external/external3" 5 | _ "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 6 | ) 7 | 8 | // @Summary Create movie 9 | // @Description models from an external package imported by mode dot 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} v1.ListResult[Customer] "" 13 | // @Router /api13 [post] 14 | func CreateMovie13() { 15 | var _ Customer 16 | } 17 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api7.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | _ "github.com/swaggo/swag/testdata/generics_package_alias/external/external4" 5 | _ "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 6 | ) 7 | 8 | // @Summary Create movie 9 | // @Description models imported from an unnamed external package 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} v1.ListResult[external4.Customer] "" 13 | // @Router /api14 [post] 14 | func CreateMovie14() { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/api/api8.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | _ "github.com/swaggo/swag/testdata/generics_package_alias/internal/path1/v1" 5 | _ "github.com/swaggo/swag/testdata/generics_package_alias/internal/path2/v1" 6 | ) 7 | 8 | // @Summary Create movie 9 | // @Description model from a package whose name conflicts with other packages 10 | // @Accept json 11 | // @Produce json 12 | // @Success 200 {object} v1.UniqueProduct "" 13 | // @Router /api15 [post] 14 | func CreateMovie15() { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/path1/v1/product.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | type ProductDto struct { 4 | Name1 string `json:"name1"` 5 | } 6 | 7 | type ListResult[T any] struct { 8 | Items1 []T `json:"items1,omitempty"` 9 | } 10 | 11 | type RenamedProductDto struct { 12 | Name11 string `json:"name11"` 13 | } // @name ProductDtoV1 14 | 15 | type RenamedListResult[T any] struct { 16 | Items11 []T `json:"items11,omitempty"` 17 | } // @name ListResultV1 18 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/path2/v1/product.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | type ProductDto struct { 4 | Name2 string `json:"name2"` 5 | } 6 | 7 | type ListResult[T any] struct { 8 | Items2 []T `json:"items2,omitempty"` 9 | } 10 | 11 | type RenamedProductDto struct { 12 | Name22 string `json:"name22"` 13 | } // @name ProductDtoV2 14 | 15 | type RenamedListResult[T any] struct { 16 | Items22 []T `json:"items22,omitempty"` 17 | } // @name ListResultV2 18 | 19 | type UniqueProduct struct { 20 | UniqueProductName string `json:"unique_product_name"` 21 | } 22 | -------------------------------------------------------------------------------- /testdata/generics_package_alias/internal/path3/v1/product.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | type ProductDto struct { 4 | Name3 string `json:"name3"` 5 | } 6 | 7 | type ListResult[T any] struct { 8 | Items3 []T `json:"items3,omitempty"` 9 | } 10 | 11 | type RenamedProductDto struct { 12 | Name33 string `json:"name33"` 13 | } // @name ProductDtoV3 14 | 15 | type RenamedListResult[T any] struct { 16 | Items33 []T `json:"items33,omitempty"` 17 | } // @name ListResultV3 18 | -------------------------------------------------------------------------------- /testdata/generics_property/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/swaggo/swag/testdata/generics_property/types" 5 | "github.com/swaggo/swag/testdata/generics_property/web" 6 | "net/http" 7 | ) 8 | 9 | type NestedResponse struct { 10 | web.GenericResponse[[]string, *uint8] 11 | Post types.Field[[]types.Post] 12 | } 13 | 14 | type Audience[T any] []T 15 | 16 | type CreateMovie struct { 17 | Name string 18 | MainActor types.Field[Person] 19 | SupportingCast types.Field[[]Person] 20 | Directors types.Field[*[]Person] 21 | CameraPeople types.Field[[]*Person] 22 | Producer types.Field[*Person] 23 | Audience Audience[Person] 24 | AudienceNames Audience[string] 25 | Detail1 types.Field[types.Field[Person]] 26 | Detail2 types.Field[types.Field[string]] 27 | } 28 | 29 | type Person struct { 30 | Name string 31 | } 32 | 33 | // @Summary List Posts 34 | // @Description Get All of the Posts 35 | // @Accept json 36 | // @Produce json 37 | // @Param data query web.PostPager true "1" 38 | // @Success 200 {object} web.PostResponse "ok" 39 | // @Success 201 {object} web.PostResponses "ok" 40 | // @Success 202 {object} web.StringResponse "ok" 41 | // @Success 203 {object} NestedResponse "ok" 42 | // @Router /posts [get] 43 | func GetPosts(w http.ResponseWriter, r *http.Request) { 44 | } 45 | 46 | // @Summary Create movie 47 | // @Description Create a new movie production 48 | // @Accept json 49 | // @Produce json 50 | // @Param data body CreateMovie true "Movie Create-Payload" 51 | // @Success 201 {object} CreateMovie "ok" 52 | // @Router /movie [post] 53 | func CreateMovieApi(w http.ResponseWriter, r *http.Request) { 54 | } 55 | -------------------------------------------------------------------------------- /testdata/generics_property/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/generics_property/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @host localhost:4000 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/posts/", api.GetPosts) 16 | http.HandleFunc("/movie/", api.CreateMovieApi) 17 | http.ListenAndServe(":8080", nil) 18 | } 19 | -------------------------------------------------------------------------------- /testdata/generics_property/types/post.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type SubField1[T any, T2 any] struct { 4 | SubValue1 T 5 | SubValue2 T2 6 | } 7 | 8 | type Field[T any] struct { 9 | Value T 10 | Value2 *T 11 | Value3 []T 12 | Value4 SubField1[T, string] 13 | } 14 | 15 | type APIBase struct { 16 | APIUrl Field[string] `json:"@uri,omitempty"` 17 | ID int `json:"id" example:"1" format:"int64"` 18 | } 19 | 20 | type Post struct { 21 | APIBase 22 | // Post name 23 | Name string `json:"name" example:"poti"` 24 | // Post data 25 | Data struct { 26 | // Post tag 27 | Tag []string `json:"name"` 28 | } `json:"data"` 29 | } 30 | -------------------------------------------------------------------------------- /testdata/generics_property/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import "github.com/swaggo/swag/testdata/generics_property/types" 4 | 5 | type PostSelector func(selector func()) 6 | 7 | type Filter interface { 8 | ~func(selector func()) 9 | } 10 | 11 | type query[T any, F Filter] interface { 12 | Where(ps ...F) T 13 | } 14 | 15 | type Pager[T query[T, F], F Filter] struct { 16 | Rows uint8 `json:"rows" form:"rows"` 17 | Page int `json:"page" form:"page"` 18 | NextID *string `json:"next_id" form:"next_id"` 19 | PrevID *string `json:"prev_id" form:"prev_id"` 20 | query T 21 | } 22 | 23 | type String string 24 | 25 | func (String) Where(ps ...PostSelector) String { 26 | return "" 27 | } 28 | 29 | type PostPager struct { 30 | Pager[String, PostSelector] 31 | Search types.Field[string] `json:"search" form:"search"` 32 | } 33 | 34 | type PostResponse struct { 35 | GenericResponse[types.Post, types.Post] 36 | } 37 | 38 | type PostResponses struct { 39 | GenericResponse[[]types.Post, types.Post] 40 | } 41 | 42 | type StringResponse struct { 43 | GenericResponse[[]string, *uint8] 44 | } 45 | 46 | type GenericResponse[T any, T2 any] struct { 47 | Items T 48 | Items2 T2 49 | } 50 | -------------------------------------------------------------------------------- /testdata/global_override/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/swaggo/swag/testdata/alias_type/types" 8 | "github.com/swaggo/swag/testdata/global_override/data" 9 | ) 10 | 11 | // @Summary Get application 12 | // @Description test get application 13 | // @ID get-application 14 | // @Accept json 15 | // @Produce json 16 | // @Success 200 {object} data.ApplicationResponse "ok" 17 | // @Router /testapi/application [get] 18 | func GetApplication(w http.ResponseWriter, r *http.Request) { 19 | var foo = data.ApplicationResponse{ 20 | Application: types.Application{ 21 | Name: "name", 22 | }, 23 | ApplicationArray: []types.Application{ 24 | {Name: "name"}, 25 | }, 26 | } 27 | log.Println(foo) 28 | //write your code 29 | } 30 | -------------------------------------------------------------------------------- /testdata/global_override/data/applicationresponse.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | typesapplication "github.com/swaggo/swag/testdata/global_override/types" 5 | ) 6 | 7 | type ApplicationResponse struct { 8 | typesapplication.TypeToEmbed 9 | 10 | Application typesapplication.Application `json:"application"` 11 | Application2 typesapplication.Application2 `json:"application2"` 12 | ApplicationArray []typesapplication.Application `json:"application_array"` 13 | ApplicationTime typesapplication.DateOnly `json:"application_time"` 14 | ShouldSkip typesapplication.ShouldSkip `json:"should_skip"` 15 | } 16 | -------------------------------------------------------------------------------- /testdata/global_override/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server Petstore server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "host": "petstore.swagger.io", 19 | "basePath": "/v2", 20 | "paths": { 21 | "/testapi/application": { 22 | "get": { 23 | "description": "test get application", 24 | "consumes": [ 25 | "application/json" 26 | ], 27 | "produces": [ 28 | "application/json" 29 | ], 30 | "summary": "Get application", 31 | "operationId": "get-application", 32 | "responses": { 33 | "200": { 34 | "description": "ok", 35 | "schema": { 36 | "$ref": "#/definitions/data.ApplicationResponse" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | }, 43 | "definitions": { 44 | "data.ApplicationResponse": { 45 | "type": "object", 46 | "properties": { 47 | "application": { 48 | "type": "string" 49 | }, 50 | "application2": { 51 | "$ref": "#/definitions/othertypes.Application" 52 | }, 53 | "application_array": { 54 | "type": "array", 55 | "items": { 56 | "type": "string" 57 | } 58 | }, 59 | "application_time": { 60 | "type": "string" 61 | }, 62 | "embedded": { 63 | "type": "string" 64 | } 65 | } 66 | }, 67 | "othertypes.Application": { 68 | "type": "object", 69 | "properties": { 70 | "id": { 71 | "type": "integer" 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /testdata/global_override/main.go: -------------------------------------------------------------------------------- 1 | package global_override 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/global_override/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | func main() { 24 | http.HandleFunc("/testapi/application", api.GetApplication) 25 | http.ListenAndServe(":8080", nil) 26 | } 27 | -------------------------------------------------------------------------------- /testdata/global_override/othertypes/application.go: -------------------------------------------------------------------------------- 1 | package othertypes 2 | 3 | type Application struct { 4 | ID int 5 | } 6 | -------------------------------------------------------------------------------- /testdata/global_override/types/application.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "time" 4 | 5 | type Application struct { 6 | Name string 7 | } 8 | 9 | type Application2 struct { 10 | Name string 11 | } 12 | 13 | type DateOnly time.Time 14 | 15 | type TypeToEmbed struct { 16 | Embedded string 17 | } 18 | 19 | type ShouldSkip struct { 20 | Name string 21 | } 22 | -------------------------------------------------------------------------------- /testdata/global_security/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // @Summary default security 8 | // @Success 200 9 | // @Router /testapi/application [get] 10 | func GetApplication(w http.ResponseWriter, r *http.Request) {} 11 | 12 | // @Summary no security 13 | // @Security 14 | // @Success 200 15 | // @Router /testapi/nosec [get] 16 | func GetNoSec(w http.ResponseWriter, r *http.Request) {} 17 | 18 | // @Summary basic security 19 | // @Security BasicAuth 20 | // @Success 200 21 | // @Router /testapi/basic [get] 22 | func GetBasic(w http.ResponseWriter, r *http.Request) {} 23 | 24 | // @Summary oauth2 write 25 | // @Security OAuth2Application[write] 26 | // @Success 200 27 | // @Router /testapi/oauth/write [get] 28 | func GetOAuthWrite(w http.ResponseWriter, r *http.Request) {} 29 | 30 | // @Summary oauth2 admin 31 | // @Security OAuth2Application[admin] 32 | // @Success 200 33 | // @Router /testapi/oauth/admin [get] 34 | func GetOAuthAdmin(w http.ResponseWriter, r *http.Request) {} 35 | -------------------------------------------------------------------------------- /testdata/global_security/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "Swagger Example API", 5 | "contact": {}, 6 | "version": "1.0" 7 | }, 8 | "paths": { 9 | "/testapi/application": { 10 | "get": { 11 | "summary": "default security", 12 | "responses": { 13 | "200": { 14 | "description": "OK" 15 | } 16 | } 17 | } 18 | }, 19 | "/testapi/basic": { 20 | "get": { 21 | "security": [ 22 | { 23 | "BasicAuth": [] 24 | } 25 | ], 26 | "summary": "basic security", 27 | "responses": { 28 | "200": { 29 | "description": "OK" 30 | } 31 | } 32 | } 33 | }, 34 | "/testapi/nosec": { 35 | "get": { 36 | "security": [], 37 | "summary": "no security", 38 | "responses": { 39 | "200": { 40 | "description": "OK" 41 | } 42 | } 43 | } 44 | }, 45 | "/testapi/oauth/admin": { 46 | "get": { 47 | "security": [ 48 | { 49 | "OAuth2Application": [ 50 | "admin" 51 | ] 52 | } 53 | ], 54 | "summary": "oauth2 admin", 55 | "responses": { 56 | "200": { 57 | "description": "OK" 58 | } 59 | } 60 | } 61 | }, 62 | "/testapi/oauth/write": { 63 | "get": { 64 | "security": [ 65 | { 66 | "OAuth2Application": [ 67 | "write" 68 | ] 69 | } 70 | ], 71 | "summary": "oauth2 write", 72 | "responses": { 73 | "200": { 74 | "description": "OK" 75 | } 76 | } 77 | } 78 | } 79 | }, 80 | "securityDefinitions": { 81 | "APIKeyAuth": { 82 | "type": "apiKey", 83 | "name": "Authorization", 84 | "in": "header" 85 | }, 86 | "BasicAuth": { 87 | "type": "basic" 88 | }, 89 | "OAuth2Application": { 90 | "type": "oauth2", 91 | "flow": "application", 92 | "tokenUrl": "https://example.com/oauth/token", 93 | "scopes": { 94 | "admin": "Grants read and write access to administrative information", 95 | "write": "Grants write access" 96 | } 97 | } 98 | }, 99 | "security": [ 100 | { 101 | "APIKeyAuth": [], 102 | "OAuth2Application": [] 103 | } 104 | ] 105 | } -------------------------------------------------------------------------------- /testdata/global_security/main.go: -------------------------------------------------------------------------------- 1 | package global_security 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | 6 | // @securityDefinitions.apikey APIKeyAuth 7 | // @in header 8 | // @name Authorization 9 | 10 | // @securityDefinitions.basic BasicAuth 11 | 12 | // @securityDefinitions.oauth2.application OAuth2Application 13 | // @tokenUrl https://example.com/oauth/token 14 | // @scope.write Grants write access 15 | // @scope.admin Grants read and write access to administrative information 16 | 17 | // @security APIKeyAuth && OAuth2Application 18 | func main() {} 19 | -------------------------------------------------------------------------------- /testdata/golist/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | /* 4 | #include "foo.h" 5 | */ 6 | import "C" 7 | import ( 8 | "fmt" 9 | "net/http" 10 | ) 11 | 12 | func PrintInt(i, j int) { 13 | res := C.add(C.int(i), C.int(j)) 14 | fmt.Println(res) 15 | } 16 | 17 | type Foo struct { 18 | ID int `json:"id"` 19 | Name string `json:"name"` 20 | PhotoUrls []string `json:"photoUrls"` 21 | Status string `json:"status"` 22 | } 23 | 24 | // GetFoo example 25 | // @Summary Get foo 26 | // @Description get foo 27 | // @ID foo 28 | // @Accept json 29 | // @Produce json 30 | // @Param some_id query int true "Some ID" 31 | // @Param some_foo formData Foo true "Foo" 32 | // @Success 200 {string} string "ok" 33 | // @Failure 400 {object} web.APIError "We need ID!!" 34 | // @Failure 404 {object} web.APIError "Can not find ID" 35 | // @Router /testapi/foo [get] 36 | func GetFoo(w http.ResponseWriter, r *http.Request) { 37 | // write your code 38 | } 39 | -------------------------------------------------------------------------------- /testdata/golist/api/foo.c: -------------------------------------------------------------------------------- 1 | int add(int a, int b) { 2 | return a + b; 3 | } -------------------------------------------------------------------------------- /testdata/golist/api/foo.h: -------------------------------------------------------------------------------- 1 | int add(int, int); -------------------------------------------------------------------------------- /testdata/golist/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/example/basic/api" 7 | goapi "github.com/swaggo/swag/testdata/golist/api" 8 | ) 9 | 10 | // @title Swagger Example API 11 | // @version 1.0 12 | // @description This is a sample server Petstore server. 13 | // @termsOfService http://swagger.io/terms/ 14 | 15 | // @contact.name API Support 16 | // @contact.url http://www.swagger.io/support 17 | // @contact.email support@swagger.io 18 | 19 | // @license.name Apache 2.0 20 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 21 | 22 | // @securityDefinitions.apikey ApiKeyAuth 23 | // @in header 24 | // @name Authorization 25 | 26 | // @query.collection.format multi 27 | // @host petstore.swagger.io 28 | // @BasePath /v2 29 | func main() { 30 | goapi.PrintInt(10, 5) 31 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 32 | http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByString) 33 | http.HandleFunc("/testapi/upload", api.Upload) 34 | http.HandleFunc("/testapi/foo", goapi.GetFoo) 35 | http.ListenAndServe(":8080", nil) 36 | } 37 | -------------------------------------------------------------------------------- /testdata/golist_disablemodule/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | /* 4 | #include "foo.h" 5 | */ 6 | import "C" 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | func PrintInt(i, j int) { 12 | res := C.add(C.int(i), C.int(j)) 13 | fmt.Println(res) 14 | } 15 | -------------------------------------------------------------------------------- /testdata/golist_disablemodule/api/foo.c: -------------------------------------------------------------------------------- 1 | int add(int a, int b) { 2 | return a + b; 3 | } -------------------------------------------------------------------------------- /testdata/golist_disablemodule/api/foo.h: -------------------------------------------------------------------------------- 1 | int add(int, int); -------------------------------------------------------------------------------- /testdata/golist_disablemodule/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/example/basic/api" 7 | internalapi "github.com/swaggo/swag/testdata/golist_disablemodule/api" 8 | ) 9 | 10 | // @title Swagger Example API 11 | // @version 1.0 12 | // @description This is a sample server Petstore server. 13 | // @termsOfService http://swagger.io/terms/ 14 | 15 | // @contact.name API Support 16 | // @contact.url http://www.swagger.io/support 17 | // @contact.email support@swagger.io 18 | 19 | // @license.name Apache 2.0 20 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 21 | 22 | // @securityDefinitions.apikey ApiKeyAuth 23 | // @in header 24 | // @name Authorization 25 | 26 | // @host petstore.swagger.io 27 | // @BasePath /v2 28 | func main() { 29 | internalapi.PrintInt(0, 1) 30 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 31 | http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByString) 32 | http.HandleFunc("/testapi/upload", api.Upload) 33 | http.ListenAndServe(":8080", nil) 34 | } 35 | -------------------------------------------------------------------------------- /testdata/golist_invalid/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/example/basic/api" 7 | "github.com/swaggo/swag/testdata/invalid_external_pkg/invalid" 8 | ) 9 | 10 | // @title Swagger Example API 11 | // @version 1.0 12 | // @description This is a sample server Petstore server. 13 | // @termsOfService http://swagger.io/terms/ 14 | 15 | // @contact.name API Support 16 | // @contact.url http://www.swagger.io/support 17 | // @contact.email support@swagger.io 18 | 19 | // @license.name Apache 2.0 20 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 21 | 22 | // @securityDefinitions.apikey ApiKeyAuth 23 | // @in header 24 | // @name Authorization 25 | 26 | // @host petstore.swagger.io 27 | // @BasePath /v2 28 | func main() { 29 | invalid.Foo() 30 | http.HandleFunc("/testapi/upload", api.Upload) 31 | http.ListenAndServe(":8080", nil) 32 | } 33 | -------------------------------------------------------------------------------- /testdata/invalid_external_pkg/invalid/normal.go: -------------------------------------------------------------------------------- 1 | package invalid 2 | 3 | func Foo() { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /testdata/invalid_external_pkg/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() {} 4 | -------------------------------------------------------------------------------- /testdata/json_field_string/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | ) 8 | 9 | type MyStruct struct { 10 | ID int `json:"id" example:"1" format:"int64"` 11 | Name string `json:"name" example:"poti"` 12 | Intvar int `json:"myint,string"` // integer as string 13 | Boolvar bool `json:",string"` // boolean as a string 14 | TrueBool bool `json:"truebool,string" example:"true"` // boolean as a string 15 | Floatvar float64 `json:",string"` // float as a string 16 | UUIDs []string `json:"uuids" type:"array,string" format:"uuid"` // string array with format 17 | } 18 | 19 | // @Summary Call DoSomething 20 | // @Description Does something 21 | // @Accept json 22 | // @Produce json 23 | // @Param body body MyStruct true "My Struct" 24 | // @Success 200 {object} MyStruct 25 | // @Failure 500 26 | // @Router /do-something [post] 27 | func DoSomething(w http.ResponseWriter, r *http.Request) { 28 | objectFromJSON := new(MyStruct) 29 | if err := json.NewDecoder(r.Body).Decode(&objectFromJSON); err != nil { 30 | w.WriteHeader(http.StatusInternalServerError) 31 | fmt.Print(err.Error()) 32 | } 33 | json.NewEncoder(w).Encode(ojbectFromJSON) 34 | } 35 | 36 | // @title Swagger Example API 37 | // @version 1.0 38 | // @description This is a sample server. 39 | // @host localhost:4000 40 | // @basePath / 41 | func main() { 42 | http.HandleFund("/do-something", DoSomething) 43 | http.ListenAndServe(":8080", nil) 44 | } 45 | -------------------------------------------------------------------------------- /testdata/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description This is a sample server Petstore server. 6 | // @description It has a lot of beautiful features. 7 | // @termsOfService http://swagger.io/terms/ 8 | 9 | // @contact.name API Support 10 | // @contact.url http://www.swagger.io/support 11 | // @contact.email support@swagger.io 12 | 13 | // @license.name Apache 2.0 14 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 15 | 16 | // @host petstore.swagger.io 17 | // @BasePath /v2 18 | // @schemes http https 19 | // @securityDefinitions.basic BasicAuth 20 | 21 | // @securityDefinitions.apikey ApiKeyAuth 22 | // @in header 23 | // @name Authorization 24 | // @description some description 25 | 26 | // @securitydefinitions.oauth2.application OAuth2Application 27 | // @tokenUrl https://example.com/oauth/token 28 | // @scope.write Grants write access 29 | // @scope.admin Grants read and write access to administrative information 30 | 31 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 32 | // @authorizationurl https://example.com/oauth/authorize 33 | // @scope.write Grants write access 34 | // @scope.admin Grants read and write access to administrative information 35 | // @x-google-audiences some_audience.google.com 36 | 37 | // @securitydefinitions.oauth2.password OAuth2Password 38 | // @tokenUrl https://example.com/oauth/token 39 | // @scope.read Grants read access 40 | // @scope.write Grants write access 41 | // @scope.admin Grants read and write access to administrative information 42 | 43 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 44 | // @tokenUrl https://example.com/oauth/token 45 | // @authorizationurl https://example.com/oauth/authorize 46 | // @scope.admin Grants read and write access to administrative information 47 | // @x-tokenname id_token 48 | 49 | // @externalDocs.description OpenAPI 50 | // @externalDocs.url https://swagger.io/resources/open-api 51 | 52 | // @x-google-endpoints [{"name":"name.endpoints.environment.cloud.goog","allowCors":true}] 53 | // @x-google-marks "marks values" 54 | // @x-logo {"url":"https://redocly.github.io/redoc/petstore-logo.png", "altText": "Petstore logo", "backgroundColor": "#FFFFFF"} 55 | 56 | func main() {} 57 | -------------------------------------------------------------------------------- /testdata/markdown.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description.markdown markdown.md 6 | // @termsOfService http://swagger.io/terms/ 7 | 8 | // @tag.name users 9 | // @tag.description.markdown 10 | 11 | func main() {} 12 | -------------------------------------------------------------------------------- /testdata/nested/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/nested2" 7 | ) 8 | 9 | type Foo struct { 10 | Field1 string `validate:"required"` 11 | OutsideData *nested2.Body 12 | InsideData Bar `validate:"required"` 13 | ArrayField1 []string `validate:"required"` 14 | ArrayField2 []Bar `validate:"required"` 15 | } 16 | 17 | type Bar struct { 18 | Field string 19 | } 20 | 21 | // @Description get Foo 22 | // @ID get-foo 23 | // @Accept json 24 | // @Produce json 25 | // @Success 200 {object} api.Foo 26 | // @Router /testapi/get-foo [get] 27 | func GetFoo(w http.ResponseWriter, r *http.Request) { 28 | //write your code 29 | var _ = Foo{} 30 | } 31 | -------------------------------------------------------------------------------- /testdata/nested/common/data.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | type Data struct { 4 | Value string `json:"message"` 5 | } 6 | -------------------------------------------------------------------------------- /testdata/nested/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": {}, 8 | "version": "1.0" 9 | }, 10 | "host": "petstore.swagger.io", 11 | "basePath": "/v2", 12 | "paths": { 13 | "/testapi/get-foo": { 14 | "get": { 15 | "description": "get Foo", 16 | "consumes": [ 17 | "application/json" 18 | ], 19 | "produces": [ 20 | "application/json" 21 | ], 22 | "operationId": "get-foo", 23 | "responses": { 24 | "200": { 25 | "description": "OK", 26 | "schema": { 27 | "$ref": "#/definitions/api.Foo" 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }, 34 | "definitions": { 35 | "api.Bar": { 36 | "type": "object", 37 | "properties": { 38 | "field": { 39 | "type": "string" 40 | } 41 | } 42 | }, 43 | "api.Foo": { 44 | "type": "object", 45 | "required": [ 46 | "arrayField1", 47 | "arrayField2", 48 | "field1", 49 | "insideData" 50 | ], 51 | "properties": { 52 | "arrayField1": { 53 | "type": "array", 54 | "items": { 55 | "type": "string" 56 | } 57 | }, 58 | "arrayField2": { 59 | "type": "array", 60 | "items": { 61 | "$ref": "#/definitions/api.Bar" 62 | } 63 | }, 64 | "field1": { 65 | "type": "string" 66 | }, 67 | "insideData": { 68 | "$ref": "#/definitions/api.Bar" 69 | }, 70 | "outsideData": { 71 | "$ref": "#/definitions/nested2.Body" 72 | } 73 | } 74 | }, 75 | "nested2.Body": { 76 | "type": "object", 77 | "properties": { 78 | "value": { 79 | "type": "string" 80 | } 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /testdata/nested/main.go: -------------------------------------------------------------------------------- 1 | package composition 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/nested/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @host petstore.swagger.io 15 | // @BasePath /v2 16 | 17 | func main() { 18 | http.HandleFunc("/testapi/get-foo", api.GetFoo) 19 | http.ListenAndServe(":8080", nil) 20 | } 21 | -------------------------------------------------------------------------------- /testdata/nested2/data.go: -------------------------------------------------------------------------------- 1 | package nested2 2 | 3 | type Body struct { 4 | Value string `json:"value"` 5 | } 6 | -------------------------------------------------------------------------------- /testdata/nested2/inner/data.go: -------------------------------------------------------------------------------- 1 | package inner 2 | -------------------------------------------------------------------------------- /testdata/non_exported_json_fields/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type MyStruct struct { 8 | ID int `json:"id" example:"1" format:"int64"` 9 | // Post name 10 | Name string `json:"name" example:"poti"` 11 | // Post data 12 | Data struct { 13 | // Post tag 14 | Tag []string `json:"name"` 15 | } `json:"data"` 16 | // not-exported variable, for internal use only, not marshaled 17 | internal1 string 18 | internal2 int 19 | internal3 bool 20 | internal4 struct { 21 | NestedInternal string 22 | } 23 | } 24 | 25 | // @Summary Call DoSomething 26 | // @Description Does something, but internal (non-exported) fields inside a struct won't be marshaled into JSON 27 | // @Accept json 28 | // @Produce json 29 | // @Success 200 {object} MyStruct 30 | // @Router /so-something [get] 31 | func DoSomething(w http.ResponseWriter, r *http.Request) { 32 | //write your code 33 | } 34 | 35 | // @title Swagger Example API 36 | // @version 1.0 37 | // @description This is a sample server. 38 | // @host localhost:4000 39 | // @basePath /api 40 | func main() { 41 | http.HandleFunc("/do-something", DoSomething) 42 | http.ListenAndServe(":8080", nil) 43 | } 44 | -------------------------------------------------------------------------------- /testdata/param_structs/structs.go: -------------------------------------------------------------------------------- 1 | package structs 2 | 3 | type FormModel struct { 4 | Foo string `form:"f" binding:"required" validate:"max=10"` 5 | // B is another field 6 | B bool 7 | } 8 | 9 | type AuthHeader struct { 10 | // Token is the auth token 11 | Token string `header:"X-Auth-Token" binding:"required"` 12 | // AnotherHeader is another header 13 | AnotherHeader int `validate:"gte=0,lte=10"` 14 | } 15 | 16 | type PathModel struct { 17 | // ID is the id 18 | Identifier int `uri:"id" binding:"required"` 19 | Name string `validate:"max=10"` 20 | } 21 | -------------------------------------------------------------------------------- /testdata/pare_outside_dependencies/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/example/basic/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | func main() { 24 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 25 | http.HandleFunc("//testapi/get-struct-array-by-string/", api.GetStructArrayByString) 26 | http.HandleFunc("/testapi/upload", api.Upload) 27 | http.ListenAndServe(":8080", nil) 28 | } 29 | -------------------------------------------------------------------------------- /testdata/parseExtension/parseExtension.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @Router /without-extension [get] 4 | func Fun() {} 5 | 6 | // @Router /with-another-extension [get] 7 | // @x-another-extension {"address": "http://backend"} 8 | func Fun2() {} 9 | 10 | // @Router /with-correct-extension [get] 11 | // @x-google-backend {"address": "http://backend"} 12 | func Fun3() {} 13 | 14 | // @Router /with-empty-comment-line [get] 15 | func FunEmptyCommentLine() {} 16 | -------------------------------------------------------------------------------- /testdata/pet/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Petstore 4 | // @version 1.0 5 | // @description This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key 'special-key' to test the authorization filters. 6 | // @termsOfService http://swagger.io/terms/ 7 | 8 | // @contact.email apiteam@swagger.io 9 | 10 | // @license.name Apache 2.0 11 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 12 | 13 | // @host petstore.swagger.io 14 | // @basePath /v2 15 | // @schemes http https 16 | func main() { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /testdata/pet/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | type Pet struct { 4 | ID int `json:"id" example:"1"` 5 | Category struct { 6 | ID int `json:"id" example:"1"` 7 | Name string `json:"name" example:"category_name"` 8 | PhotoUrls []string `json:"photo_urls" example:"http://test/image/1.jpg,http://test/image/2.jpg"` 9 | SmallCategory struct { 10 | ID int `json:"id" example:"1"` 11 | Name string `json:"name" example:"detail_category_name"` 12 | PhotoUrls []string `json:"photo_urls" example:"http://test/image/1.jpg,http://test/image/2.jpg"` 13 | } `json:"small_category"` 14 | } `json:"category"` 15 | Name string `json:"name" example:"poti"` 16 | PhotoUrls []string `json:"photo_urls" example:"http://test/image/1.jpg,http://test/image/2.jpg"` 17 | Tags []Tag `json:"tags"` 18 | Status string `json:"status"` 19 | Price float32 `json:"price" example:"3.25" multipleOf:"0.01"` 20 | IsAlive bool `json:"is_alive" example:"true"` 21 | } 22 | 23 | type Tag struct { 24 | ID int `json:"id"` 25 | Name string `json:"name"` 26 | } 27 | -------------------------------------------------------------------------------- /testdata/quotes/api.md: -------------------------------------------------------------------------------- 1 | # Title with "quotes" 2 | 3 | As we want to verify that this markdown is formatted equally in both the general 4 | API description, in a tag description and in an endpoint description, the tag 5 | defined in main.go is called api, and the markdown file name is specified 6 | manually in the description comment in api/api.go. 7 | 8 | ```json 9 | { 10 | "with": "escaped \"quotes\"", 11 | "indentedWith": "tabs", 12 | "foo": "bar", 13 | "baz": null 14 | } 15 | ``` 16 | 17 | Some more text. 18 | -------------------------------------------------------------------------------- /testdata/quotes/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // RandomFunc dogoc 4 | // @Description.markdown api 5 | // @Success 200 {string} string "ok" 6 | // @Router /random [get] 7 | func RandomFunc() {} 8 | -------------------------------------------------------------------------------- /testdata/quotes/expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemes": [], 3 | "swagger": "2.0", 4 | "info": { 5 | "description": "# Title with \"quotes\"\n\nAs we want to verify that this markdown is formatted equally in both the general\nAPI description, in a tag description and in an endpoint description, the tag\ndefined in main.go is called api, and the markdown file name is specified\nmanually in the description comment in api/api.go.\n\n```json\n{\n\t\"with\": \"escaped \\\"quotes\\\"\",\n\t\"indentedWith\": \"tabs\",\n\t\"foo\": \"bar\",\n\t\"baz\": null\n}\n```\n\nSome more text.\n", 6 | "title": "Swagger Example API", 7 | "termsOfService": "http://swagger.io/terms/", 8 | "contact": {}, 9 | "version": "1.0" 10 | }, 11 | "host": "", 12 | "basePath": "", 13 | "paths": { 14 | "/random": { 15 | "get": { 16 | "description": "# Title with \"quotes\"\n\nAs we want to verify that this markdown is formatted equally in both the general\nAPI description, in a tag description and in an endpoint description, the tag\ndefined in main.go is called api, and the markdown file name is specified\nmanually in the description comment in api/api.go.\n\n```json\n{\n\t\"with\": \"escaped \\\"quotes\\\"\",\n\t\"indentedWith\": \"tabs\",\n\t\"foo\": \"bar\",\n\t\"baz\": null\n}\n```\n\nSome more text.\n", 17 | "responses": { 18 | "200": { 19 | "description": "ok", 20 | "schema": { 21 | "type": "string" 22 | } 23 | } 24 | } 25 | } 26 | } 27 | }, 28 | "tags": [ 29 | { 30 | "description": "# Title with \"quotes\"\n\nAs we want to verify that this markdown is formatted equally in both the general\nAPI description, in a tag description and in an endpoint description, the tag\ndefined in main.go is called api, and the markdown file name is specified\nmanually in the description comment in api/api.go.\n\n```json\n{\n\t\"with\": \"escaped \\\"quotes\\\"\",\n\t\"indentedWith\": \"tabs\",\n\t\"foo\": \"bar\",\n\t\"baz\": null\n}\n```\n\nSome more text.\n", 31 | "name": "api" 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /testdata/quotes/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/swaggo/swag" 5 | "github.com/swaggo/swag/testdata/quotes/api" 6 | _ "github.com/swaggo/swag/testdata/quotes/docs" 7 | ) 8 | 9 | func ReadDoc() string { 10 | doc, _ := swag.ReadDoc() 11 | return doc 12 | } 13 | 14 | // @title Swagger Example API 15 | // @version 1.0 16 | // @description.markdown 17 | // @tag.name api 18 | // @tag.description.markdown 19 | // @termsOfService http://swagger.io/terms/ 20 | 21 | func main() { 22 | api.RandomFunc() 23 | } 24 | -------------------------------------------------------------------------------- /testdata/simple/cross/test.go: -------------------------------------------------------------------------------- 1 | package cross 2 | 3 | type Cross struct { 4 | Array []string 5 | String string 6 | } 7 | -------------------------------------------------------------------------------- /testdata/simple/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/simple/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | // @securityDefinitions.basic BasicAuth 25 | 26 | // @securityDefinitions.apikey ApiKeyAuth 27 | // @in header 28 | // @name Authorization 29 | 30 | // @securitydefinitions.oauth2.application OAuth2Application 31 | // @tokenUrl https://example.com/oauth/token 32 | // @scope.write Grants write access 33 | // @scope.admin Grants read and write access to administrative information 34 | 35 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 36 | // @authorizationurl https://example.com/oauth/authorize 37 | // @scope.write Grants write access 38 | // @scope.admin Grants read and write access to administrative information 39 | 40 | // @securitydefinitions.oauth2.password OAuth2Password 41 | // @tokenUrl https://example.com/oauth/token 42 | // @scope.read Grants read access 43 | // @scope.write Grants write access 44 | // @scope.admin Grants read and write access to administrative information 45 | 46 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 47 | // @tokenUrl https://example.com/oauth/token 48 | // @authorizationurl https://example.com/oauth/authorize 49 | // @scope.admin Grants read and write access to administrative information 50 | func main() { 51 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 52 | http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByString) 53 | http.HandleFunc("/testapi/upload", api.Upload) 54 | http.ListenAndServe(":8080", nil) 55 | } 56 | -------------------------------------------------------------------------------- /testdata/simple2/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // @Summary Add a new pet to the store 8 | // @Description get string by ID 9 | // @ID get-string-by-int 10 | // @Accept json 11 | // @Produce json 12 | // @Param some_id path int true "Some ID" Format(int64) 13 | // @Param some_id body web.Pet true "Some ID" 14 | // @Success 200 {string} string "ok" 15 | // @Failure 400 {object} web.APIError "We need ID!!" 16 | // @Failure 404 {object} web.APIError "Can not find ID" 17 | // @Router /testapi/get-string-by-int/{some_id} [get] 18 | func GetStringByInt(w http.ResponseWriter, r *http.Request) { 19 | //write your code 20 | } 21 | 22 | // @Description get struct array by ID 23 | // @ID get-struct-array-by-string 24 | // @Accept json 25 | // @Produce json 26 | // @Param some_id path string true "Some ID" 27 | // @Param category query int true "Category" Enums(1, 2, 3) 28 | // @Param offset query int true "Offset" Minimum(0) default(0) 29 | // @Param limit query int true "Limit" Maximum(50) default(10) 30 | // @Param q query string true "q" Minlength(1) Maxlength(50) default("") 31 | // @Success 200 {string} string "ok" 32 | // @Failure 400 {object} web.APIError "We need ID!!" 33 | // @Failure 404 {object} web.APIError "Can not find ID" 34 | // @Security ApiKeyAuth 35 | // @Security BasicAuth 36 | // @Security OAuth2Application[write] 37 | // @Security OAuth2Implicit[read, admin] 38 | // @Security OAuth2AccessCode[read] 39 | // @Security OAuth2Password[admin] 40 | // @Router /testapi/get-struct-array-by-string/{some_id} [get] 41 | func GetStructArrayByString(w http.ResponseWriter, r *http.Request) { 42 | //write your code 43 | } 44 | 45 | // @Summary Upload file 46 | // @Description Upload file 47 | // @ID file.upload 48 | // @Accept multipart/form-data 49 | // @Produce json 50 | // @Param file formData file true "this is a test file" 51 | // @Success 200 {string} string "ok" 52 | // @Failure 400 {object} web.APIError "We need ID!!" 53 | // @Failure 404 {object} web.APIError "Can not find ID" 54 | // @Router /file/upload [post] 55 | func Upload(w http.ResponseWriter, r *http.Request) { 56 | //write your code 57 | } 58 | 59 | // @Summary use Anonymous field 60 | // @Success 200 {object} web.RevValue "ok" 61 | func AnonymousField() { 62 | 63 | } 64 | 65 | // @Summary use pet2 66 | // @Success 200 {object} web.Pet2 "ok" 67 | func Pet2() { 68 | 69 | } 70 | 71 | type Pet3 struct { 72 | ID int `json:"id"` 73 | } 74 | -------------------------------------------------------------------------------- /testdata/simple2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/simple2/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | // @securityDefinitions.basic BasicAuth 25 | 26 | // @securityDefinitions.apikey ApiKeyAuth 27 | // @in header 28 | // @name Authorization 29 | 30 | // @securitydefinitions.oauth2.application OAuth2Application 31 | // @tokenUrl https://example.com/oauth/token 32 | // @scope.write Grants write access 33 | // @scope.admin Grants read and write access to administrative information 34 | 35 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 36 | // @authorizationurl https://example.com/oauth/authorize 37 | // @scope.write Grants write access 38 | // @scope.admin Grants read and write access to administrative information 39 | 40 | // @securitydefinitions.oauth2.password OAuth2Password 41 | // @tokenUrl https://example.com/oauth/token 42 | // @scope.read Grants read access 43 | // @scope.write Grants write access 44 | // @scope.admin Grants read and write access to administrative information 45 | 46 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 47 | // @tokenUrl https://example.com/oauth/token 48 | // @authorizationurl https://example.com/oauth/authorize 49 | // @scope.admin Grants read and write access to administrative information 50 | func main() { 51 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 52 | http.HandleFunc("//testapi/get-struct-array-by-string/", api.GetStructArrayByString) 53 | http.HandleFunc("/testapi/upload", api.Upload) 54 | http.ListenAndServe(":8080", nil) 55 | } 56 | -------------------------------------------------------------------------------- /testdata/simple2/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "database/sql" 5 | "math/big" 6 | "strconv" 7 | "time" 8 | 9 | uuid "github.com/gofrs/uuid" 10 | "github.com/shopspring/decimal" 11 | ) 12 | 13 | type TimestampTime struct { 14 | time.Time 15 | } 16 | 17 | func (t *TimestampTime) MarshalJSON() ([]byte, error) { 18 | bin := make([]byte, 16) 19 | bin = strconv.AppendInt(bin[:0], t.Time.Unix(), 10) 20 | return bin, nil 21 | } 22 | 23 | func (t *TimestampTime) UnmarshalJSON(bin []byte) error { 24 | v, err := strconv.ParseInt(string(bin), 10, 64) 25 | if err != nil { 26 | return err 27 | } 28 | t.Time = time.Unix(v, 0) 29 | return nil 30 | } 31 | 32 | type Pet struct { 33 | ID int `example:"1" format:"int64"` 34 | Category struct { 35 | ID int `example:"1"` 36 | Name string `example:"category_name"` 37 | PhotoUrls []string `example:"http://test/image/1.jpg,http://test/image/2.jpg" format:"url"` 38 | SmallCategory struct { 39 | ID int `example:"1"` 40 | Name string `example:"detail_category_name" validate:"required"` 41 | PhotoUrls []string `example:"http://test/image/1.jpg,http://test/image/2.jpg"` 42 | } 43 | } 44 | Name string `example:"poti"` 45 | PhotoUrls []string `example:"http://test/image/1.jpg,http://test/image/2.jpg"` 46 | Tags []Tag 47 | Pets *[]Pet2 48 | Pets2 []*Pet2 49 | Status string 50 | Price float32 `example:"3.25" validate:"required,gte=0,lte=130" multipleOf:"0.01"` 51 | IsAlive bool `example:"true"` 52 | Data interface{} 53 | Hidden string `json:"-"` 54 | UUID uuid.UUID 55 | Decimal decimal.Decimal 56 | CustomString CustomString 57 | CustomStringArr []CustomString 58 | NullInt sql.NullInt64 `swaggertype:"integer"` 59 | Coeffs []big.Float `swaggertype:"array,number"` 60 | Birthday TimestampTime `swaggertype:"primitive,integer"` 61 | } 62 | 63 | type CustomString string 64 | 65 | type Tag struct { 66 | ID int `format:"int64"` 67 | Name string 68 | Pets []Pet 69 | } 70 | 71 | type Pet2 struct { 72 | ID int 73 | MiddleName *string 74 | DeletedAt *time.Time 75 | } 76 | 77 | type APIError struct { 78 | ErrorCode int 79 | ErrorMessage string 80 | CreatedAt time.Time 81 | } 82 | 83 | type RevValueBase struct { 84 | Status bool 85 | 86 | Err int32 87 | } 88 | type RevValue struct { 89 | RevValueBase 90 | 91 | Data int 92 | } 93 | -------------------------------------------------------------------------------- /testdata/simple3/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Summary Add a new pet to the store 6 | // @Description get string by ID 7 | // @ID get-string-by-int 8 | // @Accept json 9 | // @Produce json 10 | // @Param some_id path int true "Some ID" Format(int64) 11 | // @Param some_id body web.Pet true "Some ID" 12 | // @Success 200 {string} string "ok" 13 | // @Failure 400 {object} web.APIError "We need ID!!" 14 | // @Failure 404 {object} web.APIError "Can not find ID" 15 | // @Router /testapi/get-string-by-int/{some_id} [get] 16 | func GetStringByInt(w http.ResponseWriter, r *http.Request) { 17 | //write your code 18 | } 19 | 20 | // @Description get struct array by ID 21 | // @ID get-struct-array-by-string 22 | // @Accept json 23 | // @Produce json 24 | // @Param some_id path string true "Some ID" 25 | // @Param category query int true "Category" Enums(1, 2, 3) 26 | // @Param offset query int true "Offset" Minimum(0) default(0) 27 | // @Param limit query int true "Limit" Maximum(50) default(10) 28 | // @Param q query string true "q" Minlength(1) Maxlength(50) default("") 29 | // @Success 200 {string} string "ok" 30 | // @Failure 400 {object} web.APIError "We need ID!!" 31 | // @Failure 404 {object} web.APIError "Can not find ID" 32 | // @Security ApiKeyAuth 33 | // @Security BasicAuth 34 | // @Security OAuth2Application[write] 35 | // @Security OAuth2Implicit[read, admin] 36 | // @Security OAuth2AccessCode[read] 37 | // @Security OAuth2Password[admin] 38 | // @Router /testapi/get-struct-array-by-string/{some_id} [get] 39 | func GetStructArrayByString(w http.ResponseWriter, r *http.Request) { 40 | //write your code 41 | } 42 | 43 | // @Summary Upload file 44 | // @Description Upload file 45 | // @ID file.upload 46 | // @Accept multipart/form-data 47 | // @Produce json 48 | // @Param file formData file true "this is a test file" 49 | // @Success 200 {string} string "ok" 50 | // @Failure 400 {object} web.APIError "We need ID!!" 51 | // @Failure 404 {object} web.APIError "Can not find ID" 52 | // @Router /file/upload [post] 53 | func Upload(w http.ResponseWriter, r *http.Request) { 54 | //write your code 55 | } 56 | 57 | // @Summary use Anonymous field 58 | // @Success 200 {object} web.RevValue "ok" 59 | func AnonymousField() { 60 | 61 | } 62 | 63 | // @Summary use pet2 64 | // @Success 200 {object} web.Pet2 "ok" 65 | func Pet2() { 66 | 67 | } 68 | 69 | type Pet3 struct { 70 | ID int `json:"id"` 71 | } 72 | -------------------------------------------------------------------------------- /testdata/simple3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/simple3/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @host petstore.swagger.io 22 | // @BasePath /v2 23 | 24 | // @securityDefinitions.basic BasicAuth 25 | 26 | // @securityDefinitions.apikey ApiKeyAuth 27 | // @in header 28 | // @name Authorization 29 | 30 | // @securitydefinitions.oauth2.application OAuth2Application 31 | // @tokenUrl https://example.com/oauth/token 32 | // @scope.write Grants write access 33 | // @scope.admin Grants read and write access to administrative information 34 | 35 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 36 | // @authorizationurl https://example.com/oauth/authorize 37 | // @scope.write Grants write access 38 | // @scope.admin Grants read and write access to administrative information 39 | 40 | // @securitydefinitions.oauth2.password OAuth2Password 41 | // @tokenUrl https://example.com/oauth/token 42 | // @scope.read Grants read access 43 | // @scope.write Grants write access 44 | // @scope.admin Grants read and write access to administrative information 45 | 46 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 47 | // @tokenUrl https://example.com/oauth/token 48 | // @authorizationurl https://example.com/oauth/authorize 49 | // @scope.admin Grants read and write access to administrative information 50 | func main() { 51 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 52 | http.HandleFunc("//testapi/get-struct-array-by-string/", api.GetStructArrayByString) 53 | http.HandleFunc("/testapi/upload", api.Upload) 54 | http.ListenAndServe(":8080", nil) 55 | } 56 | -------------------------------------------------------------------------------- /testdata/simple3/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | 6 | uuid "github.com/gofrs/uuid" 7 | "github.com/shopspring/decimal" 8 | ) 9 | 10 | type Pet struct { 11 | ID int `example:"1" format:"int64"` 12 | Category struct { 13 | ID int `example:"1"` 14 | Name string `example:"category_name"` 15 | PhotoURLs []string `example:"http://test/image/1.jpg,http://test/image/2.jpg" format:"url"` 16 | SmallCategory struct { 17 | ID int `example:"1"` 18 | Name string `example:"detail_category_name"` 19 | PhotoURLs []string `example:"http://test/image/1.jpg,http://test/image/2.jpg"` 20 | } 21 | } 22 | Name string `example:"poti"` 23 | PhotoURLs []string `example:"http://test/image/1.jpg,http://test/image/2.jpg"` 24 | Tags []Tag 25 | Pets *[]Pet2 26 | Pets2 []*Pet2 27 | Status string 28 | Price float32 `example:"3.25" multipleOf:"0.01"` 29 | IsAlive bool `example:"true"` 30 | Data interface{} 31 | Hidden string `json:"-"` 32 | UUID uuid.UUID 33 | Decimal decimal.Decimal 34 | Function func() 35 | } 36 | 37 | type Tag struct { 38 | ID int `format:"int64"` 39 | Name string 40 | Pets []Pet 41 | } 42 | 43 | type Pet2 struct { 44 | ID int 45 | MiddleName *string 46 | DeletedAt *time.Time 47 | } 48 | 49 | type APIError struct { 50 | ErrorCode int 51 | ErrorMessage string 52 | CreatedAt time.Time 53 | } 54 | 55 | type RevValueBase struct { 56 | Status bool 57 | 58 | Err int32 59 | } 60 | type RevValue struct { 61 | RevValueBase 62 | 63 | Data int 64 | } 65 | -------------------------------------------------------------------------------- /testdata/simple_cgo/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Summary Add a new pet to the store 6 | // @Description get string by ID 7 | // @ID get-string-by-int 8 | // @Accept json 9 | // @Produce json 10 | // @Param some_id path int true "Some ID" Format(int64) 11 | // @Param some_id body int true "Some ID" 12 | // @Success 200 {string} string "ok" 13 | // @Failure 400 {object} string "We need ID!!" 14 | // @Failure 404 {object} string "Can not find ID" 15 | // @Router /testapi/get-string-by-int/{some_id} [get] 16 | func GetStringByInt(w http.ResponseWriter, r *http.Request) { 17 | } 18 | -------------------------------------------------------------------------------- /testdata/simple_cgo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #include 5 | 6 | void Hello(){ 7 | printf("Hello world\n"); 8 | } 9 | */ 10 | import "C" 11 | 12 | import ( 13 | "net/http" 14 | 15 | "github.com/swaggo/swag/testdata/simple_cgo/api" 16 | ) 17 | 18 | // @title Swagger Example API 19 | // @version 1.0 20 | // @description This is a sample server Petstore server. 21 | // @termsOfService http://swagger.io/terms/ 22 | 23 | // @contact.name API Support 24 | // @contact.url http://www.swagger.io/support 25 | // @contact.email support@swagger.io 26 | 27 | // @license.name Apache 2.0 28 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 29 | 30 | // @host petstore.swagger.io 31 | // @BasePath /v2 32 | 33 | // @securityDefinitions.basic BasicAuth 34 | 35 | // @securityDefinitions.apikey ApiKeyAuth 36 | // @in header 37 | // @name Authorization 38 | 39 | // @securitydefinitions.oauth2.application OAuth2Application 40 | // @tokenUrl https://example.com/oauth/token 41 | // @scope.write Grants write access 42 | // @scope.admin Grants read and write access to administrative information 43 | 44 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 45 | // @authorizationurl https://example.com/oauth/authorize 46 | // @scope.write Grants write access 47 | // @scope.admin Grants read and write access to administrative information 48 | 49 | // @securitydefinitions.oauth2.password OAuth2Password 50 | // @tokenUrl https://example.com/oauth/token 51 | // @scope.read Grants read access 52 | // @scope.write Grants write access 53 | // @scope.admin Grants read and write access to administrative information 54 | 55 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 56 | // @tokenUrl https://example.com/oauth/token 57 | // @authorizationurl https://example.com/oauth/authorize 58 | // @scope.admin Grants read and write access to administrative information 59 | func main() { 60 | C.Hello() 61 | 62 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) 63 | http.ListenAndServe(":8080", nil) 64 | } 65 | -------------------------------------------------------------------------------- /testdata/single_file_api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @title Swagger Example API 4 | // @version 1.0 5 | // @description This is a sample server Petstore server. 6 | // @description It has a lot of beautiful features. 7 | // @termsOfService http://swagger.io/terms/ 8 | 9 | // @Summary test op 10 | // @Router /test [get] 11 | // @Description This belongs to the operation, not the general API! 12 | func op() bool { 13 | return true 14 | } 15 | -------------------------------------------------------------------------------- /testdata/state/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @State admin 6 | // @Summary Add a new pet to the store 7 | // @Description get string by ID 8 | // @ID admin.get-string-by-int 9 | // @Accept json 10 | // @Produce json 11 | // @Param some_id path int true "Some ID" Format(int64) 12 | // @Param some_id body web.Pet true "Some ID" 13 | // @Success 200 {string} string "ok" 14 | // @Failure 400 {object} web.APIError "We need ID!!" 15 | // @Failure 404 {object} web.APIError "Can not find ID" 16 | // @Router /admin/testapi/get-string-by-int/{some_id} [get] 17 | func GetStringByInt(w http.ResponseWriter, r *http.Request) { 18 | //write your code 19 | } 20 | 21 | // @State admin 22 | // @Description get struct array by ID 23 | // @ID admin.get-struct-array-by-string 24 | // @Accept json 25 | // @Produce json 26 | // @Param some_id path string true "Some ID" 27 | // @Param category query int true "Category" Enums(1, 2, 3) 28 | // @Param offset query int true "Offset" Minimum(0) default(0) 29 | // @Param limit query int true "Limit" Maximum(50) default(10) 30 | // @Param q query string true "q" Minlength(1) Maxlength(50) default("") 31 | // @Success 200 {string} string "ok" 32 | // @Failure 400 {object} web.APIError "We need ID!!" 33 | // @Failure 404 {object} web.APIError "Can not find ID" 34 | // @Security ApiKeyAuth 35 | // @Security BasicAuth 36 | // @Security OAuth2Application[write] 37 | // @Security OAuth2Implicit[read, admin] 38 | // @Security OAuth2AccessCode[read] 39 | // @Security OAuth2Password[admin] 40 | // @Router /admin/testapi/get-struct-array-by-string/{some_id} [get] 41 | func GetStructArrayByString(w http.ResponseWriter, r *http.Request) { 42 | //write your code 43 | } 44 | 45 | // @State admin 46 | // @Summary Upload file 47 | // @Description Upload file 48 | // @ID admin.file.upload 49 | // @Accept multipart/form-data 50 | // @Produce json 51 | // @Param file formData file true "this is a test file" 52 | // @Success 200 {string} string "ok" 53 | // @Failure 400 {object} web.APIError "We need ID!!" 54 | // @Failure 404 {object} web.APIError "Can not find ID" 55 | // @Router /admin/file/upload [post] 56 | func Upload(w http.ResponseWriter, r *http.Request) { 57 | //write your code 58 | } 59 | 60 | // @State admin 61 | // @Summary use Anonymous field 62 | // @Success 200 {object} web.RevValue "ok" 63 | func AnonymousField() { 64 | 65 | } 66 | 67 | // @State admin 68 | // @Summary use pet2 69 | // @Success 200 {object} web.Pet2 "ok" 70 | func Pet2() { 71 | 72 | } 73 | 74 | type Pet3 struct { 75 | ID int `json:"id"` 76 | } 77 | -------------------------------------------------------------------------------- /testdata/state/api/api_user.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @State user 6 | // @Summary Add a new pet to the store 7 | // @Description get string by ID 8 | // @ID get-string-by-int 9 | // @Accept json 10 | // @Produce json 11 | // @Param some_id path int true "Some ID" Format(int64) 12 | // @Param some_id body web.Pet true "Some ID" 13 | // @Success 200 {string} string "ok" 14 | // @Failure 400 {object} web.APIError "We need ID!!" 15 | // @Failure 404 {object} web.APIError "Can not find ID" 16 | // @Router /testapi/get-string-by-int/{some_id} [get] 17 | func GetStringByIntUser(w http.ResponseWriter, r *http.Request) { 18 | //write your code 19 | } 20 | 21 | // @State user 22 | // @Description get struct array by ID 23 | // @ID get-struct-array-by-string 24 | // @Accept json 25 | // @Produce json 26 | // @Param some_id path string true "Some ID" 27 | // @Param category query int true "Category" Enums(1, 2, 3) 28 | // @Param offset query int true "Offset" Minimum(0) default(0) 29 | // @Param limit query int true "Limit" Maximum(50) default(10) 30 | // @Param q query string true "q" Minlength(1) Maxlength(50) default("") 31 | // @Success 200 {string} string "ok" 32 | // @Failure 400 {object} web.APIError "We need ID!!" 33 | // @Failure 404 {object} web.APIError "Can not find ID" 34 | // @Security ApiKeyAuth 35 | // @Security BasicAuth 36 | // @Security OAuth2Application[write] 37 | // @Security OAuth2Implicit[read, admin] 38 | // @Security OAuth2AccessCode[read] 39 | // @Security OAuth2Password[admin] 40 | // @Router /testapi/get-struct-array-by-string/{some_id} [get] 41 | func GetStructArrayByStringUser(w http.ResponseWriter, r *http.Request) { 42 | //write your code 43 | } 44 | 45 | // @State user 46 | // @Summary Upload file 47 | // @Description Upload file 48 | // @ID file.upload 49 | // @Accept multipart/form-data 50 | // @Produce json 51 | // @Param file formData file true "this is a test file" 52 | // @Success 200 {string} string "ok" 53 | // @Failure 400 {object} web.APIError "We need ID!!" 54 | // @Failure 404 {object} web.APIError "Can not find ID" 55 | // @Router /file/upload [post] 56 | func UploadUser(w http.ResponseWriter, r *http.Request) { 57 | //write your code 58 | } 59 | 60 | // @State user 61 | // @Summary use Anonymous field 62 | // @Success 200 {object} web.RevValue "ok" 63 | func AnonymousFieldUser() { 64 | 65 | } 66 | 67 | // @State user 68 | // @Summary use pet2 69 | // @Success 200 {object} web.Pet2 "ok" 70 | func Pet2User() { 71 | 72 | } 73 | 74 | type Pet3User struct { 75 | ID int `json:"id"` 76 | } 77 | -------------------------------------------------------------------------------- /testdata/state/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/state/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @termsOfService http://swagger.io/terms/ 13 | 14 | // @contact.name API Support 15 | // @contact.url http://www.swagger.io/support 16 | // @contact.email support@swagger.io 17 | 18 | // @license.name Apache 2.0 19 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 20 | 21 | // @hostState admin petstore-admin.swagger.io 22 | // @hostState user petstore-user.swagger.io 23 | // @BasePath /v3 24 | func main() { 25 | state := "admin" // "admin" or "user" 26 | switch state { 27 | case "admin": 28 | http.HandleFunc("/admin/testapi/get-string-by-int/", api.GetStringByInt) 29 | http.HandleFunc("/admin/testapi/get-struct-array-by-string/", api.GetStructArrayByString) 30 | http.HandleFunc("/admin/testapi/upload", api.Upload) 31 | http.ListenAndServe(":8080", nil) 32 | case "user": 33 | http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByIntUser) 34 | http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByStringUser) 35 | http.HandleFunc("/testapi/upload", api.UploadUser) 36 | http.ListenAndServe(":8080", nil) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /testdata/state/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | 6 | uuid "github.com/gofrs/uuid" 7 | "github.com/shopspring/decimal" 8 | ) 9 | 10 | type Pet struct { 11 | ID int `example:"1" format:"int64"` 12 | Category struct { 13 | ID int `example:"1"` 14 | Name string `example:"category_name"` 15 | PhotoURLs []string `example:"http://test/image/1.jpg,http://test/image/2.jpg" format:"url"` 16 | SmallCategory struct { 17 | ID int `example:"1"` 18 | Name string `example:"detail_category_name"` 19 | PhotoURLs []string `example:"http://test/image/1.jpg,http://test/image/2.jpg"` 20 | } 21 | } 22 | Name string `example:"poti"` 23 | PhotoURLs []string `example:"http://test/image/1.jpg,http://test/image/2.jpg"` 24 | Tags []Tag 25 | Pets *[]Pet2 26 | Pets2 []*Pet2 27 | Status string 28 | Price float32 `example:"3.25" multipleOf:"0.01"` 29 | IsAlive bool `example:"true"` 30 | Data interface{} 31 | Hidden string `json:"-"` 32 | UUID uuid.UUID 33 | Decimal decimal.Decimal 34 | Function func() 35 | } 36 | 37 | type Tag struct { 38 | ID int `format:"int64"` 39 | Name string 40 | Pets []Pet 41 | } 42 | 43 | type Pet2 struct { 44 | ID int 45 | MiddleName *string 46 | DeletedAt *time.Time 47 | } 48 | 49 | type APIError struct { 50 | ErrorCode int 51 | ErrorMessage string 52 | CreatedAt time.Time 53 | } 54 | 55 | type RevValueBase struct { 56 | Status bool 57 | 58 | Err int32 59 | } 60 | type RevValue struct { 61 | RevValueBase 62 | 63 | Data int 64 | } 65 | -------------------------------------------------------------------------------- /testdata/struct_comment/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/http" 4 | 5 | // @Summary Add a new pet to the store 6 | // @Description get string by ID 7 | // @Accept json 8 | // @Produce json 9 | // @Param post_id path int true "Some ID" Format(int64) 10 | // @Success 200 {string} web.Post 11 | // @Failure 400 {object} web.APIError "We need ID!!" 12 | // @Failure 404 {object} web.APIError "Can not find ID" 13 | // @Router /posts/{post_id} [get] 14 | func GetPost(w http.ResponseWriter, r *http.Request) { 15 | //write your code 16 | } 17 | -------------------------------------------------------------------------------- /testdata/struct_comment/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/swaggo/swag/testdata/struct_comment/api" 7 | ) 8 | 9 | // @title Swagger Example API 10 | // @version 1.0 11 | // @description This is a sample server Petstore server. 12 | // @host localhost:4000 13 | // @basePath /api 14 | func main() { 15 | http.HandleFunc("/posts/", api.GetPost) 16 | http.ListenAndServe(":8080", nil) 17 | } 18 | -------------------------------------------------------------------------------- /testdata/struct_comment/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Post struct { 8 | ID int `json:"id" example:"1" format:"int64"` 9 | // Post name 10 | Name string `json:"name" example:"poti"` 11 | // Post data 12 | Data struct { 13 | // Post tag 14 | Tag []string `json:"name"` 15 | } `json:"data"` 16 | } 17 | 18 | // APIError 19 | // @Description API error 20 | // @Description with information about it 21 | // Other some summary 22 | type APIError struct { 23 | // Error an Api error 24 | Error string // Error this is Line comment 25 | // Error `number` tick comment 26 | ErrorNo int64 27 | ErrorCtx string // Error `context` tick comment 28 | CreatedAt time.Time // Error time 29 | } 30 | -------------------------------------------------------------------------------- /testdata/tags/apes.md: -------------------------------------------------------------------------------- 1 | ## Apes 2 | 3 | Apes are very cool! -------------------------------------------------------------------------------- /testdata/tags/api.md: -------------------------------------------------------------------------------- 1 | ## CoolApi Title 2 | 3 | ### Cool API SubTitle 4 | 5 | We love markdown! -------------------------------------------------------------------------------- /testdata/tags/cats.md: -------------------------------------------------------------------------------- 1 | ## Cats 2 | 3 | Cats are also very cool! -------------------------------------------------------------------------------- /testdata/tags/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @description.markdown 4 | // @tag.name dogs 5 | // @tag.description Dogs are cool 6 | // @tag.name cats 7 | // @tag.description Cats are the devil 8 | // @tag.docs.url https://google.de 9 | // @tag.docs.description google is super useful to find out that cats are evil! 10 | // @tag.name apes 11 | // @tag.description Apes are also cool 12 | func main() {} 13 | -------------------------------------------------------------------------------- /testdata/tags2/apes.md: -------------------------------------------------------------------------------- 1 | ## Apes 2 | 3 | Apes are very cool! -------------------------------------------------------------------------------- /testdata/tags2/api.md: -------------------------------------------------------------------------------- 1 | ## CoolApi Title 2 | 3 | ### Cool API SubTitle 4 | 5 | We love markdown! -------------------------------------------------------------------------------- /testdata/tags2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @description.markdown 4 | // @tag.name dogs 5 | // @tag.description Dogs are cool 6 | // @tag.name cats 7 | // @tag.description Cats are the devil 8 | // @tag.docs.url https://google.de 9 | // @tag.docs.description google is super useful to find out that cats are evil! 10 | // @tag.name apes 11 | // @tag.description.markdown 12 | func main() {} 13 | -------------------------------------------------------------------------------- /testdata/tags_nonexistend_tag/apes.md: -------------------------------------------------------------------------------- 1 | ## Apes 2 | 3 | Apes are very cool! -------------------------------------------------------------------------------- /testdata/tags_nonexistend_tag/api.md: -------------------------------------------------------------------------------- 1 | ## CoolApi Title 2 | 3 | ### Cool API SubTitle 4 | 5 | We love markdown! -------------------------------------------------------------------------------- /testdata/tags_nonexistend_tag/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @description.markdown 4 | // @tag.name dogs 5 | // @tag.description Dogs are cool 6 | // @tag.name cats 7 | // @tag.description Cats are the devil 8 | // @tag.docs.url https://google.de 9 | // @tag.docs.description google is super useful to find out that cats are evil! 10 | // @tag.description.markdown 11 | func main() {} 12 | -------------------------------------------------------------------------------- /testdata/templated.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // @termsOfService http://swagger.io/terms/ 4 | 5 | // @contact.name API Support 6 | // @contact.url http://www.swagger.io/support 7 | // @contact.email support@swagger.io 8 | 9 | // @license.name Apache 2.0 10 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 11 | 12 | // @securityDefinitions.basic BasicAuth 13 | 14 | // @securityDefinitions.apikey ApiKeyAuth 15 | // @in header 16 | // @name Authorization 17 | 18 | // @securitydefinitions.oauth2.application OAuth2Application 19 | // @tokenUrl https://example.com/oauth/token 20 | // @scope.write Grants write access 21 | // @scope.admin Grants read and write access to administrative information 22 | 23 | // @securitydefinitions.oauth2.implicit OAuth2Implicit 24 | // @authorizationurl https://example.com/oauth/authorize 25 | // @scope.write Grants write access 26 | // @scope.admin Grants read and write access to administrative information 27 | 28 | // @securitydefinitions.oauth2.password OAuth2Password 29 | // @tokenUrl https://example.com/oauth/token 30 | // @scope.read Grants read access 31 | // @scope.write Grants write access 32 | // @scope.admin Grants read and write access to administrative information 33 | 34 | // @securitydefinitions.oauth2.accessCode OAuth2AccessCode 35 | // @tokenUrl https://example.com/oauth/token 36 | // @authorizationurl https://example.com/oauth/authorize 37 | // @scope.admin Grants read and write access to administrative information 38 | 39 | // @externalDocs.description OpenAPI 40 | // @externalDocs.url https://swagger.io/resources/open-api 41 | 42 | // @x-google-endpoints [{"name":"name.endpoints.environment.cloud.goog","allowCors":true}] 43 | // @x-google-marks "marks values" 44 | 45 | func main() {} 46 | -------------------------------------------------------------------------------- /testdata/users.md: -------------------------------------------------------------------------------- 1 | Users Tag Markdown Description -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | import "unicode" 4 | 5 | // FieldsFunc split a string s by a func splitter into max n parts 6 | func FieldsFunc(s string, f func(rune2 rune) bool, n int) []string { 7 | // A span is used to record a slice of s of the form s[start:end]. 8 | // The start index is inclusive and the end index is exclusive. 9 | type span struct { 10 | start int 11 | end int 12 | } 13 | spans := make([]span, 0, 32) 14 | 15 | // Find the field start and end indices. 16 | // Doing this in a separate pass (rather than slicing the string s 17 | // and collecting the result substrings right away) is significantly 18 | // more efficient, possibly due to cache effects. 19 | start := -1 // valid span start if >= 0 20 | for end, rune := range s { 21 | if f(rune) { 22 | if start >= 0 { 23 | spans = append(spans, span{start, end}) 24 | // Set start to a negative value. 25 | // Note: using -1 here consistently and reproducibly 26 | // slows down this code by a several percent on amd64. 27 | start = ^start 28 | } 29 | } else { 30 | if start < 0 { 31 | start = end 32 | if n > 0 && len(spans)+1 >= n { 33 | break 34 | } 35 | } 36 | } 37 | } 38 | 39 | // Last field might end at EOF. 40 | if start >= 0 { 41 | spans = append(spans, span{start, len(s)}) 42 | } 43 | 44 | // Create strings from recorded field indices. 45 | a := make([]string, len(spans)) 46 | for i, span := range spans { 47 | a[i] = s[span.start:span.end] 48 | } 49 | return a 50 | } 51 | 52 | // FieldsByAnySpace split a string s by any space character into max n parts 53 | func FieldsByAnySpace(s string, n int) []string { 54 | return FieldsFunc(s, unicode.IsSpace, n) 55 | } 56 | -------------------------------------------------------------------------------- /utils_test.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "testing" 6 | ) 7 | 8 | func TestFieldsByAnySpace(t *testing.T) { 9 | type args struct { 10 | s string 11 | n int 12 | } 13 | tests := []struct { 14 | name string 15 | args args 16 | want []string 17 | }{ 18 | {"test1", 19 | args{ 20 | " aa bb cc dd ff", 21 | 2, 22 | }, 23 | []string{"aa", "bb\tcc dd \t\tff"}, 24 | }, 25 | {"test2", 26 | args{ 27 | ` aa "bb cc dd ff"`, 28 | 2, 29 | }, 30 | []string{"aa", `"bb cc dd ff"`}, 31 | }, 32 | } 33 | for _, tt := range tests { 34 | t.Run(tt.name, func(t *testing.T) { 35 | assert.Equalf(t, tt.want, FieldsByAnySpace(tt.args.s, tt.args.n), "FieldsByAnySpace(%v, %v)", tt.args.s, tt.args.n) 36 | }) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /version.go: -------------------------------------------------------------------------------- 1 | package swag 2 | 3 | // Version of swag. 4 | const Version = "v1.16.4" 5 | --------------------------------------------------------------------------------