{"id":14987658,"url":"https://github.com/wi2l/fizz","last_synced_at":"2025-04-05T03:07:58.201Z","repository":{"id":37431761,"uuid":"124098943","full_name":"wI2L/fizz","owner":"wI2L","description":":lemon: Gin wrapper with OpenAPI 3 spec generation","archived":false,"fork":false,"pushed_at":"2024-06-26T11:19:03.000Z","size":584,"stargazers_count":222,"open_issues_count":19,"forks_count":54,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-05T03:07:25.538Z","etag":null,"topics":["gin","go","golang","openapi3","router"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/wI2L/fizz","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wI2L.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-06T15:32:24.000Z","updated_at":"2025-03-21T14:02:45.000Z","dependencies_parsed_at":"2024-09-30T01:01:22.133Z","dependency_job_id":"d6972fc7-892d-4a66-bbc3-15cc6b6b82db","html_url":"https://github.com/wI2L/fizz","commit_stats":{"total_commits":64,"total_committers":24,"mean_commits":"2.6666666666666665","dds":0.5625,"last_synced_commit":"fe54d355ba0184693a3dd34eeacfe1a03487dff1"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Ffizz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Ffizz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Ffizz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Ffizz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wI2L","download_url":"https://codeload.github.com/wI2L/fizz/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247280269,"owners_count":20912967,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gin","go","golang","openapi3","router"],"created_at":"2024-09-24T14:15:07.731Z","updated_at":"2025-04-05T03:07:58.175Z","avatar_url":"https://github.com/wI2L.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003ch1 align=\"center\"\u003eFizz\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\u003cimg src=\"images/lemon.png\" height=\"200px\" width=\"auto\" alt=\"Gin Fizz\"\u003e\u003c/p\u003e\u003cp align=\"center\"\u003eFizz is a wrapper for \u003cstrong\u003eGin\u003c/strong\u003e based on \u003cstrong\u003e\u003ca href=\"https://github.com/loopfz/gadgeto/tree/master/tonic\"\u003egadgeto/tonic\u003c/a\u003e\u003c/strong\u003e.\u003c/p\u003e\n\u003cp align=\"center\"\u003eIt generates wrapping gin-compatible handlers that do all the repetitive work and wrap the call to your handlers. It can also generates an \u003ci\u003ealmost\u003c/i\u003e complete \u003cstrong\u003eOpenAPI 3\u003c/strong\u003e specification of your API.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://pkg.go.dev/github.com/wI2L/fizz?tab=doc\"\u003e\u003cimg src=\"https://img.shields.io/static/v1?label=godev\u0026message=reference\u0026color=00add8\u0026logo=go\"\u003e\u003c/a\u003e\n   \u003ca href=\"https://goreportcard.com/report/wI2L/fizz\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/wI2L/fizz\"\u003e\u003c/a\u003e\n   \u003ca href=\"https://github.com/wI2L/fizz/actions\"\u003e\u003cimg src=\"https://github.com/wI2L/fizz/workflows/CI/badge.svg\"\u003e\u003c/a\u003e\n   \u003ca href=\"https://codecov.io/gh/wI2L/fizz\"\u003e\u003cimg src=\"https://codecov.io/gh/wI2L/fizz/branch/master/graph/badge.svg\"/\u003e\u003c/a\u003e\n   \u003ca href=\"https://github.com/wI2L/fizz/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/tag/wI2L/fizz?color=blueviolet\u0026label=version\u0026sort=semver\"\u003e\u003c/a\u003e\n   \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\"\u003e\u003c/a\u003e\n   \u003ca href=\"https://github.com/avelino/awesome-go\"\u003e\u003cimg src=\"https://awesome.re/mentioned-badge.svg\"\u003e\u003c/a\u003e\n\u003cbr\u003e\n\u003c/p\u003e\n\n---\n\n### Getting started\n\nTo create a Fizz instance, you can pass an existing *Gin* engine to `fizz.NewFromEngine`, or use `fizz.New` that will use a new default *Gin* engine.\n\n```go\nengine := gin.Default()\nengine.Use(...) // register global middlewares\n\nf := fizz.NewFromEngine(engine)\n```\n\nA Fizz instance implements the `http.HandlerFunc` interface, which means it can be used as the base handler of your HTTP server.\n```go\nsrv := \u0026http.Server{\n   Addr:    \":4242\",\n   Handler: f,\n}\nsrv.ListenAndServe()\n```\n\n### Handlers\n\nFizz abstracts the `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `HEAD` and `TRACE` methods of a *Gin* engine. These functions accept a variadic list of handlers as the last parameter, but since Fizz relies on *tonic* to retrieve the informations required to generate the *OpenAPI* specification of the operation, **only one of the handlers registered MUST be wrapped with Tonic**.\n\nIn the following example, the `BarHandler` is a simple middleware that will be executed before the `FooHandler`, but the generator will use the input/output type of the `FooHandler` to generate the specification of the operation.\n\n```go\nfunc BarHandler(c *gin.Context) { ... }\nfunc FooHandler(*gin.Context, *Foo) (*Bar, error) { ... }\n\nfizz := fizz.New()\nfizz.GET(\"/foo/bar\", nil, BarHandler, tonic.Handler(FooHandler, 200))\n```\n\nHowever, registering only standard handlers that follow the `gin.HandlerFunc` signature is accepted, but the *OpenAPI* generator will ignore the operation and it won't appear in the specification.\n\n### Operation informations\n\nTo enrich an operation, you can pass a list of optional `OperationOption` functions as the second parameters of the `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS` and `HEAD` methods.\n\n```go\n// Set the default response description.\n// A default status text will be created from the code if it is omitted.\nfizz.StatusDescription(desc string)\n\n// Set the summary of the operation.\nfizz.Summary(summary string)\nfizz.Summaryf(format string, a ...interface{})\n\n// Set the description of the operation.\nfizz.Description(desc string)\nfizz.Descriptionf(format string, a ...interface{})\n\n// Override the ID of the operation.\n// Must be a unique string used to identify the operation among\n// all operations described in the API.\nfizz.ID(id string)\n\n// Mark the operation as deprecated.\nfizz.Deprecated(deprecated bool)\n\n// Add an additional response to the operation.\n// The example argument will populate a single example in the response schema.\n// For populating multiple examples, use fizz.ResponseWithExamples.\n// Notice that example and examples fields are mutually exclusive.\n// model, header, and example may be `nil`.\nfizz.Response(statusCode, desc string, model interface{}, headers []*ResponseHeader, example interface{})\n\n// ResponseWithExamples is a variant of Response that supports providing multiple examples.\n// Examples argument will populate multiple examples in the response schema.\n// For populating a single example, use fizz.Response.\n// Notice that example and examples fields are mutually exclusive.\n// model, header, and examples may be `nil`.\nfizz.ResponseWithExamples(statusCode, desc string, model interface{}, headers []*ResponseHeader, examples map[string]interface{})\n\n// Add an additional header to the default response.\n// Model can be of any type, and may also be `nil`,\n// in which case the string type will be used as default.\nfizz.Header(name, desc string, model interface{})\n\n// Override the binding model of the operation.\nfizz.InputModel(model interface{})\n\n// Overrides the top-level security requirement of an operation.\n// Note that this function can be used more than once to add several requirements.\nfizz.Security(security *openapi.SecurityRequirement)\n\n// Add an empty security requirement to this operation to make other security requirements optional.\nfizz.WithOptionalSecurity()\n\n// Remove any top-level security requirements for this operation.\nfizz.WithoutSecurity()\n\n// Add a Code Sample to the operation.\nfizz.XCodeSample(codeSample *XCodeSample)\n\n// Mark the operation as internal. The x-internal flag is interpreted by third-party tools and it only impacts the visual documentation rendering.\nfizz.XInternal()\n```\n\n**NOTES:**\n* `fizz.InputModel` allows to override the operation input regardless of how the handler implementation really binds the request parameters. It is the developer responsibility to ensure that the binding matches the OpenAPI specification.\n* The first argument of the `fizz.Reponse` method which represents an HTTP status code is of type *string* because the spec accept the value `default`. See the [Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responsesObject) documentation for more informations.\n\nTo help you declare additional headers, predefined variables for Go primitives types that you can use as the third argument of the `fizz.Header` method are available:\n```go\nvar (\n   Integer  int32\n   Long     int64\n   Float    float32\n   Double   float64\n   String   string\n   Byte     []byte\n   Binary   []byte\n   Boolean  bool\n   DateTime time.Time\n)\n```\n\n### Groups\n\nExactly like you would do with *Gin*, you can create a group of routes using the method `Group`. Unlike *Gin* own method, Fizz's one takes two other optional arguments, `name` and `description`. These parameters will be used to create a tag in the **OpenAPI** specification that will be applied to all the routes added to the group.\n\n```go\ngrp := f.Group(\"/subpath\", \"MyGroup\", \"Group description\", middlewares...)\n```\nIf the `name` parameter is empty, the tag won't be created and it won't be used.\n\nSubgroups of subgroups can be created to an infinite depth, according yo your needs.\n\n```go\nfoo := f.Group(\"/foo\", \"Foo\", \"Foo group\")\n\n// all routes registered on group bar will have\n// a relative path starting with /foo/bar\nbar := f.Group(\"/bar\", \"Bar\", \"Bar group\")\n\n// /foo/bar/{barID}\nbar.GET(\"/:barID\", nil, tonic.Handler(MyBarHandler, 200))\n```\n\nThe `Use` method can be used with groups to register middlewares after their creation.\n```go\ngrp.Use(middleware1, middleware2, ...)\n```\n\n## Tonic\n\nThe subpackage *tonic* handles path/query/header/body parameters binding in a single consolidated input object which allows you to remove all the boilerplate code that retrieves and tests the presence of various parameters. The *OpenAPI* generator make use of the input/output types informations of a tonic-wrapped handler reported by *tonic* to document the operation in the specification.\n\nThe handlers wrapped with *tonic* must follow the following signature.\n```go\nfunc(*gin.Context, [input object ptr]) ([output object], error)\n```\nInput and output objects are both optional, as such, the minimal accepted signature is:\n```go\nfunc(*gin.Context) error\n```\n\nTo wrap a handler with *tonic*, use the `tonic.Handler` method. It takes a function that follow the above signature and a default status code and return a `gin.HandlerFunc` function that can be used when you register a route with Fizz of *Gin*.\n\nOutput objects can be of any type, and will be marshalled to the desired media type.\nNote that the input object **MUST always be a pointer to a struct**, or the tonic wrapping will panic at runtime.\n\nIf you use closures as handlers, please note that they will all have the same name, and the generator will return an error. To overcome this problem, you have to explicitely set the ID of an operation when you register the handler.\n\n```go\nfunc MyHandler() gin.HandlerFunc {\n   return tonic.Handler(func(c *gin.Context) error {}, 200)\n}\n\nfizz.GET(\"/foo\", []fizz.OperationOption{\n   fizz.ID(\"MyOperationID\")\n}, MyHandler())\n```\n\n### Location tags\n\n*tonic* uses three struct tags to recognize the parameters it should bind to the input object of your tonic-wrapped handlers:\n- `path`: bind from the request path\n- `query`: bind from the request query string\n- `header`: bind from the request headers\n\nThe fields that doesn't use one of these tags will be considered as part of the request body.\n\nThe value of each struct tag represents the name of the field in each location, with options.\n```go\ntype MyHandlerParams struct {\n   ID  int64     `path:\"id\"`\n   Foo string    `query:\"foo\"`\n   Bar time.Time `header:\"x-foo-bar\"`\n}\n```\n\n*tonic* will automatically convert the value extracted from the location described by the tag to the appropriate type before binding.\n\n**NOTE**: A path parameter is always required and will appear required in the spec regardless of the `validate` tag content.\n\n### Additional tags\n\nYou can use additional tags. Some will be interpreted by *tonic*, others will be exclusively used to enrich the *OpenAPI* specification.\n\n| name          | description                                                                                                                                                                                                                                                                           |\n| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `default`     | *tonic* will bind this value if none was passed with the request. This should not be used if a field is also required. Read the [documentation](https://swagger.io/docs/specification/describing-parameters/) (section _Common Mistakes_) for more informations about this behaviour. |\n| `description` | Add a description of the field in the spec.                                                                                                                                                                                                                                           |\n| `deprecated`  | Indicates if the field is deprecated. Accepted values are `1`, `t`, `T`, `TRUE`, `true`, `True`, `0`, `f`, `F`, `FALSE`. Invalid value are considered to be false.                                                                                                                    |\n| `enum`        | A coma separated list of acceptable values for the parameter.                                                                                                                                                                                                                         |\n| `example`     | An example value to be used in OpenAPI specification. See [section below](#Providing-Examples-for-Custom-Types) for the demonstration on how to provide example for custom types.                                                                                                     |\n| `format`      | Override the format of the field in the specification. Read the [documentation](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#dataTypeFormat) for more informations.                                                                                     |\n| `validate`    | Field validation rules. Read the [documentation](https://godoc.org/gopkg.in/go-playground/validator.v8) for more informations.                                                                                                                                                        |\n| `explode`     | Specifies whether arrays should generate separate parameters for each array item or object property (limited to query parameters with *form* style). Accepted values are `1`, `t`, `T`, `TRUE`, `true`, `True`, `0`, `f`, `F`, `FALSE`. Invalid value are considered to be false.     |\n\n### JSON/XML\n\nThe JSON/XML encoders usually omit a field that has the tag `\"-\"`. This behaviour is reproduced by the *OpenAPI* generator ; a field with this tag won't appear in the properties of the schema.\n\nIn the following example, the field `Input` is used only for binding request body parameters and won't appear in the output encoding while `Output` will be marshaled but will not be used for parameters binding.\n```go\ntype Model struct {\n\tInput  string `json:\"-\"`\n\tOutput string `json:\"output\" binding:\"-\"`\n}\n```\n\n### Request body\n\nIf you want to make a request body field mandatory, you can use the tag `validate:\"required\"`. The validator used by *tonic* will ensure that the field is present.\nTo be able to make a difference between a missing value and the zero value of a type, use a pointer.\n\nTo explicitly ignore a parameter from the request body, use the tag `binding:\"-\"`.\n\nNote that the *OpenAPI* generator will ignore request body parameters for the routes with a method that is one of `GET`, `DELETE` or `HEAD`.\n   \u003e GET, DELETE and HEAD are no longer allowed to have request body because it does not have defined semantics as per [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4.3).\n\t[*source*](https://swagger.io/docs/specification/describing-request-body/)\n\n### Schema validation\n\nThe *OpenAPI* generator recognize some tags of the [go-playground/validator.v8](https://gopkg.in/go-playground/validator.v8) package and translate those to the [properties of the schema](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#properties) that are taken from the [JSON Schema definition](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6).\n\nThe supported tags are: [len](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Length), [max](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Maximum), [min](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Mininum), [eq](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Equals), [gt](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Greater_Than), [gte](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Greater_Than_or_Equal), [lt](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Less_Than), [lte](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Less_Than_or_Equal).\n\nBased on the type of the field that carry the tag, the fields `maximum`, `minimum`, `minLength`, `maxLength`, `minItems`, `maxItems`, `minProperties` and `maxProperties` of its **JSON Schema** will be filled accordingly.\n\n## OpenAPI specification\n\nTo serve the generated OpenAPI specification in either `JSON` or `YAML` format, use the handler returned by the `fizz.OpenAPI` method.\n\nTo enrich the specification, you can provide additional informations. Head to the [OpenAPI 3 spec](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#infoObject) for more informations about the API informations that you can specify, or take a look at the type `openapi.Info` in the file [`openapi/spec.go`](openapi/spec.go#L25).\n\n```go\nf := fizz.New()\ninfos := \u0026openapi.Info{\n   Title:       \"Fruits Market\",\n   Description: `This is a sample Fruits market server.`,\n   Version:     \"1.0.0\",\n}\nf.GET(\"/openapi.json\", nil, f.OpenAPI(infos, \"json\"))\n```\n**NOTE**: The generator will never panic. However, it is strongly recommended to call `fizz.Errors` to retrieve and handle the errors that may have occured during the generation of the specification before starting your API.\n\n#### Servers information\n\nIf the OpenAPI specification refers to an API that is not hosted on the same domain, or using a path prefix not included in the spec, you will have to declare server information. This can be achieved using the `f.Generator().SetServers` method.\n\n```go\nf := fizz.New()\nf.Generator().SetServers([]*openapi.Server{\n   {\n      Description: \"Fruits Market - production\",\n      URL:         \"https://example.org/api/1.0\",\n   },\n})\n```\n\n#### Security schemes\n\nIf your API requires authentication, you have to declare the security schemes that can be used by the operations. This can be achieved using the `f.Generator().SetSecuritySchemes` method.\n\n```go\nf := fizz.New()\nf.Generator().SetSecuritySchemes(map[string]*openapi.SecuritySchemeOrRef{\n   \"apiToken\": {\n      SecurityScheme: \u0026openapi.SecurityScheme{\n         Type: \"apiKey\",\n         In:   \"header\",\n         Name: \"x-api-token\",\n      },\n   },\n})\n```\n\nOnce defined, the security schemes will be available for all operations. You can override them on an per-operation basis using the `fizz.Security()` function.\n\n```go\nfizz.Security(\u0026openapi.SecurityRequirement{\n   \"apiToken\": []string{},\n})\n```\n\n#### Components\n\nThe output types of your handlers are registered as components within the generated specification. By default, the name used for each component is composed of the package and type name concatenated using _CamelCase_ style, and does not contain the full import path. As such, please ensure that you don't use the same type name in two eponym package in your application.\n\nThe names of the components can be customized in two different ways.\n\n##### Global override\n\nOverride the name of a type globally before registering your handlers. This has the highest precedence.\n```go\nf := fizz.New()\nf.Generator().OverrideTypeName(reflect.TypeOf(T{}), \"OverridedName\")\n```\n\n##### Interface\n\nImplements the `openapi.Typer` interface on your types.\n```go\nfunc (*T) TypeName() string { return \"OverridedName\" }\n```\n**WARNING:** You **MUST** not rely on the method receiver to return the name, because the method will be called on a new instance created by the generator with the `reflect` package.\n\n#### Custom schemas\n\nThe spec generator creates OpenAPI schemas for your types based on their [reflection kind](https://golang.org/pkg/reflect/#Kind).\nIf you want to control the output schema of a type manually, you can implement the `DataType` interface for this type.\n\nFor example, given a UUID version 4 type, declared as a struct, that should appear as a string with a custom format.\n```go\ntype UUIDv4 struct { ... }\n\nfunc (*UUIDv4) Format() string { return \"uuid\" }\nfunc (*UUIDv4) Type() string { return \"string\" }\n```\n\nThe schema of the type will look like the following instead of describing all the fields of the struct.\n```json\n{\n   \"type\": \"string\",\n   \"format\": \"uuid\"\n}\n```\n\nIf you want to override the `nullable` property of a type, you can implement the `Nullable` interface for this type.\n\nFor example, if [`sql.NullString`](https://pkg.go.dev/database/sql#NullString) is not referenced by a pointer in your model but you still want it to be \"nullable\":\n\n```go\ntype NullString sql.NullString\n\nfunc (NullString) Nullable() bool { return true }\n```\n\n**WARNING:** You **MUST** not rely on the method receivers to return the type and format, because these methods will be called on a new instance created by the generator with the `reflect` package.\n\nYou can also override manually the type and format using `OverrideDataType()`. This has the highest precedence.\n```go\nfizz.Generator().OverrideDataType(reflect.TypeOf(\u0026UUIDv4{}), \"string\", \"uuid\")\n```\n\n##### Native and imported types support\n\nFizz supports some native and imported types. A schema with a proper type and format will be generated automatically, removing the need for creating your own custom schema.\n\n* [`time.Time`](https://golang.org/pkg/time/#Time)\n* [`time.Duration`](https://golang.org/pkg/time/#Duration)\n* [`net.URL`](https://golang.org/pkg/net/url/#URL)\n* [`net.IP`](https://golang.org/pkg/net/#IP)\n\nNote that, according to the doc, the inherent version of the address is a semantic property, and thus cannot be determined by Fizz. Therefore, the format returned is simply `ip`. If you want to specify the version, you can use the tags `format:\"ipv4\"` or `format:\"ipv6\"`.\n* [`uuid.UUID`](https://godoc.org/github.com/gofrs/uuid#UUID)\n\n#### Markdown\n\n\u003e Throughout the specification description fields are noted as supporting CommonMark markdown formatting. Where OpenAPI tooling renders rich text it MUST support, at a minimum, markdown syntax as described by CommonMark 0.27. Tooling MAY choose to ignore some CommonMark features to address security concerns.\n[*source*](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#rich-text-formatting)\n\nTo help you write markdown descriptions in Go, a simple builder is available in the sub-package `markdown`. This is quite handy to avoid conflicts with backticks that are both used in Go for litteral multi-lines strings and code blocks in markdown.\n\n#### Providing Examples for Custom Types\nTo be able to provide examples for custom types, they must implement the `json.Marshaler` and/or `yaml.Marshaler` and the following interface:\n```go\ntype Exampler interface {\n       ParseExample(v string) (interface{}, error)\n}\n```\n\nIf the custom type implements the interface, Fizz will pass the value from the `example` tag to the `ParseExample` method and use the return value as the example in the OpenAPI specification.\n\n## Known limitations\n\n- Since *OpenAPI* is based on the *JSON Schema* specification itself, objects (Go maps) with keys that are not of type `string` are not supported and will be ignored during the generation of the specification.\n- Recursive embedding of the same type is not supported, at any level of recursion. The generator will warn and skip the offending fields.\n   ```go\n   type A struct {\n      Foo int\n      *A   // ko, embedded and same type as parent\n      A *A // ok, not embedded\n      *B   // ok, different type\n   }\n\n   type B struct {\n      Bar string\n      *A // ko, type B is embedded in type A\n      *C // ok, type C does not contains an embedded field of type A\n   }\n\n   type C struct {\n      Baz bool\n   }\n   ```\n\n## Examples\n\nA simple runnable API is available in `examples/market`.\n```shell\ngo build\n./market\n# Retrieve the specification marshaled in JSON.\ncurl -i http://localhost:4242/openapi.json\n```\n\n## Credits\n\nFizz is based on [gin-gonic/gin](https://github.com/gin-gonic/gin) and use [gadgeto/tonic](https://github.com/loopfz/gadgeto/tree/master/tonic). :heart:\n\n\u003cp align=\"right\"\u003e\u003cimg src=\"https://forthebadge.com/images/badges/built-with-swag.svg\"\u003e\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwi2l%2Ffizz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwi2l%2Ffizz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwi2l%2Ffizz/lists"}