mirror of
https://github.com/gofiber/fiber.git
synced 2025-07-10 20:48:28 +00:00
* feat: Add All method to Bind This commit introduces a new `All` method to the `Bind` struct, enabling the binding of request data from multiple sources (URI parameters, body, query parameters, headers, and cookies) into a single struct. The `All` method iterates through the available binding sources, applying them in a predefined precedence order. It merges the values from each source into the output struct, only updating fields that are currently unset. Changes: - Added `All` method to `Bind` struct. - Added `mergeStruct` helper function to merge struct values. - Added `isZero` helper function to check if a value is zero. - Added a test case for the `All` method in `bind_test.go` to validate its functionality. * feat: Enhance Bind.All with comprehensive testing and configuration The changes include: - Added `RequestConfig` struct to encapsulate request configuration (ContentType, Body, Headers, Cookies, Query). - Implemented `ApplyTo` method on `RequestConfig` to apply the configuration to the context. - Created multiple test cases for `Bind.All` covering successful binding, missing fields, overriding query parameters, and form binding. - Added a test case `Test_Bind_All_Uri_Precedence` to validate the precedence of URI parameters. - Added benchmark test `BenchmarkBind_All` to measure the performance of the `Bind.All` method. - Refactored the `TestBind_All` to use the new `RequestConfig` and assertion libraries. * fix: Correct form binding in Test_Bind_All * refactor: Improve Bind.All test and struct field ordering - Reordered fields in `RequestConfig` and `User` structs for field alignment - Updated `Test_Bind_All` to use `require.NoError` for more robust error checking. - Corrected header key casing in `Test_Bind_All` to `X-User-Role` to match the struct tag. - Added `t.Parallel()` to the test function to enable parallel test execution. * feat: Document Bind.All function in API documentation This commit adds documentation for the `Bind.All` function to the API documentation. The documentation includes: - A description of the function's purpose and precedence order for binding data from different sources (URI, body, query, headers, cookies). * docs: lint Bind.All documentation * fix: Update parameter tags from 'param' to 'uri' in bind_test.go * fix: Update parameter tags from 'param' to 'uri' in bind.md * test: Replace assert with require in bind_test.go * feat: Add support for unified binding with defined precedence order in whats_new.md --------- Co-authored-by: RW <rene@gofiber.io>
719 lines
18 KiB
Markdown
719 lines
18 KiB
Markdown
---
|
|
id: bind
|
|
title: 📎 Bind
|
|
description: Binds the request and response items to a struct.
|
|
sidebar_position: 4
|
|
toc_max_heading_level: 4
|
|
---
|
|
|
|
Bindings are used to parse the request/response body, query parameters, cookies, and much more into a struct.
|
|
|
|
:::info
|
|
All binder returned values are only valid within the handler. Do not store any references.
|
|
Make copies or use the [**`Immutable`**](./ctx.md) setting instead. [Read more...](../#zero-allocation)
|
|
:::
|
|
|
|
## Binders
|
|
|
|
- [Body](#body)
|
|
- [Form](#form)
|
|
- [JSON](#json)
|
|
- [XML](#xml)
|
|
- [CBOR](#cbor)
|
|
- [Cookie](#cookie)
|
|
- [Header](#header)
|
|
- [Query](#query)
|
|
- [RespHeader](#respheader)
|
|
- [URI](#uri)
|
|
- [All](#all)
|
|
|
|
### Body
|
|
|
|
Binds the request body to a struct.
|
|
|
|
It is important to specify the correct struct tag based on the content type to be parsed. For example, if you want to parse a JSON body with a field called `Pass`, you would use a struct field with `json:"pass"`.
|
|
|
|
| Content-Type | Struct Tag |
|
|
| ----------------------------------- | ---------- |
|
|
| `application/x-www-form-urlencoded` | `form` |
|
|
| `multipart/form-data` | `form` |
|
|
| `application/json` | `json` |
|
|
| `application/xml` | `xml` |
|
|
| `text/xml` | `xml` |
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) Body(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `json:"name" xml:"name" form:"name"`
|
|
Pass string `json:"pass" xml:"pass" form:"pass"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Body(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` commands:
|
|
|
|
```bash
|
|
# JSON
|
|
curl -X POST -H "Content-Type: application/json" --data "{\"name\":\"john\",\"pass\":\"doe\"}" localhost:3000
|
|
|
|
# XML
|
|
curl -X POST -H "Content-Type: application/xml" --data "<login><name>john</name><pass>doe</pass></login>" localhost:3000
|
|
|
|
# Form URL-Encoded
|
|
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data "name=john&pass=doe" localhost:3000
|
|
|
|
# Multipart Form
|
|
curl -X POST -F name=john -F pass=doe http://localhost:3000
|
|
```
|
|
|
|
### Form
|
|
|
|
Binds the request or multipart form body data to a struct.
|
|
|
|
It is important to specify the correct struct tag based on the content type to be parsed. For example, if you want to parse a form body with a field called `Pass`, you would use a struct field with `form:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) Form(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `form:"name"`
|
|
Pass string `form:"pass"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Form(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` commands for both `application/x-www-form-urlencoded` and `multipart/form-data`:
|
|
|
|
```bash
|
|
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data "name=john&pass=doe" localhost:3000
|
|
```
|
|
|
|
```bash
|
|
curl -X POST -H "Content-Type: multipart/form-data" -F "name=john" -F "pass=doe" localhost:3000
|
|
```
|
|
|
|
:::info
|
|
If you need to bind multipart file, you can use `*multipart.FileHeader`, `*[]*multipart.FileHeader` or `[]*multipart.FileHeader` as a field type.
|
|
:::
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `form:"name"`
|
|
Pass string `form:"pass"`
|
|
Avatar *multipart.FileHeader `form:"avatar"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Form(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
log.Println(p.Avatar.Filename) // file.txt
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl -X POST -H "Content-Type: multipart/form-data" -F "name=john" -F "pass=doe" -F 'avatar=@filename' localhost:3000
|
|
```
|
|
|
|
### JSON
|
|
|
|
Binds the request JSON body to a struct.
|
|
|
|
It is important to specify the correct struct tag based on the content type to be parsed. For example, if you want to parse a JSON body with a field called `Pass`, you would use a struct field with `json:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) JSON(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `json:"name"`
|
|
Pass string `json:"pass"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().JSON(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl -X POST -H "Content-Type: application/json" --data "{\"name\":\"john\",\"pass\":\"doe\"}" localhost:3000
|
|
```
|
|
|
|
### XML
|
|
|
|
Binds the request XML body to a struct.
|
|
|
|
It is important to specify the correct struct tag based on the content type to be parsed. For example, if you want to parse an XML body with a field called `Pass`, you would use a struct field with `xml:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) XML(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
// Field names should start with an uppercase letter
|
|
type Person struct {
|
|
Name string `xml:"name"`
|
|
Pass string `xml:"pass"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().XML(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl -X POST -H "Content-Type: application/xml" --data "<login><name>john</name><pass>doe</pass></login>" localhost:3000
|
|
```
|
|
|
|
### CBOR
|
|
|
|
Binds the request CBOR body to a struct.
|
|
|
|
It is important to specify the correct struct tag based on the content type to be parsed. For example, if you want to parse a CBOR body with a field called `Pass`, you would use a struct field with `cbor:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) CBOR(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
// Field names should start with an uppercase letter
|
|
type Person struct {
|
|
Name string `cbor:"name"`
|
|
Pass string `cbor:"pass"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().CBOR(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl -X POST -H "Content-Type: application/cbor" --data "\xa2dnamedjohndpasscdoe" localhost:3000
|
|
```
|
|
|
|
### Cookie
|
|
|
|
This method is similar to [Body Binding](#body), but for cookie parameters.
|
|
It is important to use the struct tag `cookie`. For example, if you want to parse a cookie with a field called `Age`, you would use a struct field with `cookie:"age"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) Cookie(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `cookie:"name"`
|
|
Age int `cookie:"age"`
|
|
Job bool `cookie:"job"`
|
|
}
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Cookie(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // Joseph
|
|
log.Println(p.Age) // 23
|
|
log.Println(p.Job) // true
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl --cookie "name=Joseph; age=23; job=true" http://localhost:8000/
|
|
```
|
|
|
|
### Header
|
|
|
|
This method is similar to [Body Binding](#body), but for request headers.
|
|
It is important to use the struct tag `header`. For example, if you want to parse a request header with a field called `Pass`, you would use a struct field with `header:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) Header(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `header:"name"`
|
|
Pass string `header:"pass"`
|
|
Products []string `header:"products"`
|
|
}
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Header(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
log.Println(p.Products) // [shoe hat]
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl "http://localhost:3000/" -H "name: john" -H "pass: doe" -H "products: shoe,hat"
|
|
```
|
|
|
|
### Query
|
|
|
|
This method is similar to [Body Binding](#body), but for query parameters.
|
|
It is important to use the struct tag `query`. For example, if you want to parse a query parameter with a field called `Pass`, you would use a struct field with `query:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) Query(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `query:"name"`
|
|
Pass string `query:"pass"`
|
|
Products []string `query:"products"`
|
|
}
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Query(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
// Depending on fiber.Config{EnableSplittingOnParsers: false} - default
|
|
log.Println(p.Products) // ["shoe,hat"]
|
|
// With fiber.Config{EnableSplittingOnParsers: true}
|
|
// log.Println(p.Products) // ["shoe", "hat"]
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl "http://localhost:3000/?name=john&pass=doe&products=shoe,hat"
|
|
```
|
|
|
|
:::info
|
|
For more parser settings, please refer to [Config](fiber.md#enablesplittingonparsers)
|
|
:::
|
|
|
|
### RespHeader
|
|
|
|
This method is similar to [Body Binding](#body), but for response headers.
|
|
It is important to use the struct tag `respHeader`. For example, if you want to parse a response header with a field called `Pass`, you would use a struct field with `respHeader:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) RespHeader(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `respHeader:"name"`
|
|
Pass string `respHeader:"pass"`
|
|
Products []string `respHeader:"products"`
|
|
}
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().RespHeader(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
log.Println(p.Products) // [shoe hat]
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl "http://localhost:3000/" -H "name: john" -H "pass: doe" -H "products: shoe,hat"
|
|
```
|
|
|
|
### URI
|
|
|
|
This method is similar to [Body Binding](#body), but for path parameters.
|
|
It is important to use the struct tag `uri`. For example, if you want to parse a path parameter with a field called `Pass`, you would use a struct field with `uri:"pass"`.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) URI(out any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
// GET http://example.com/user/111
|
|
app.Get("/user/:id", func(c fiber.Ctx) error {
|
|
param := struct {
|
|
ID uint `uri:"id"`
|
|
}{}
|
|
|
|
if err := c.Bind().URI(¶m); err != nil {
|
|
return err
|
|
}
|
|
|
|
// ...
|
|
return c.SendString(fmt.Sprintf("User ID: %d", param.ID))
|
|
})
|
|
```
|
|
|
|
### All
|
|
|
|
The `All` function binds data from various sources (URL parameters, request body, query parameters, headers, and cookies) into the provided struct pointer `out`. It processes each source in a predefined order, applying data to the struct fields based on their tags.
|
|
|
|
#### Precedence Order
|
|
|
|
The binding sources have the following precedence:
|
|
|
|
1. **URL Parameters (URI)**
|
|
2. **Request Body (e.g., JSON or form data)**
|
|
3. **Query Parameters**
|
|
4. **Request Headers**
|
|
5. **Cookies**
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) All(out any) error
|
|
```
|
|
|
|
``` go title="Example"
|
|
type User struct {
|
|
Name string `query:"name" json:"name" form:"name"`
|
|
Email string `json:"email" form:"email"`
|
|
Role string `header:"X-User-Role"`
|
|
SessionID string `json:"session_id" cookie:"session_id"`
|
|
ID int `uri:"id" query:"id" json:"id" form:"id"`
|
|
}
|
|
|
|
app.Post("/users", func(c fiber.Ctx) error {
|
|
user := new(User)
|
|
|
|
if err := c.Bind().All(user); err != nil {
|
|
return err
|
|
}
|
|
|
|
// All available data is now bound to the user struct
|
|
return c.JSON(user)
|
|
})
|
|
```
|
|
|
|
## Custom
|
|
|
|
To use custom binders, you have to use this method.
|
|
|
|
You can register them using the [RegisterCustomBinder](./app.md#registercustombinder) method of the Fiber instance.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) Custom(name string, dest any) error
|
|
```
|
|
|
|
```go title="Example"
|
|
app := fiber.New()
|
|
|
|
// My custom binder
|
|
type customBinder struct{}
|
|
|
|
func (cb *customBinder) Name() string {
|
|
return "custom"
|
|
}
|
|
|
|
func (cb *customBinder) MIMETypes() []string {
|
|
return []string{"application/yaml"}
|
|
}
|
|
|
|
func (cb *customBinder) Parse(c fiber.Ctx, out any) error {
|
|
// parse YAML body
|
|
return yaml.Unmarshal(c.Body(), out)
|
|
}
|
|
|
|
// Register custom binder
|
|
app.RegisterCustomBinder(&customBinder{})
|
|
|
|
type User struct {
|
|
Name string `yaml:"name"`
|
|
}
|
|
|
|
// curl -X POST http://localhost:3000/custom -H "Content-Type: application/yaml" -d "name: John"
|
|
app.Post("/custom", func(c fiber.Ctx) error {
|
|
var user User
|
|
// Use Custom binder by name
|
|
if err := c.Bind().Custom("custom", &user); err != nil {
|
|
return err
|
|
}
|
|
return c.JSON(user)
|
|
})
|
|
```
|
|
|
|
Internally, custom binders are also used in the [Body](#body) method.
|
|
The `MIMETypes` method is used to check if the custom binder should be used for the given content type.
|
|
|
|
## Options
|
|
|
|
For more control over error handling, you can use the following methods.
|
|
|
|
### WithAutoHandling
|
|
|
|
If you want to handle binder errors automatically, you can use `WithAutoHandling`.
|
|
If there's an error, it will return the error and set HTTP status to `400 Bad Request`.
|
|
This function does NOT panic therefor you must still return on error explicitly
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) WithAutoHandling() *Bind
|
|
```
|
|
|
|
### WithoutAutoHandling
|
|
|
|
To handle binder errors manually, you can use the `WithoutAutoHandling` method.
|
|
It's the default behavior of the binder.
|
|
|
|
```go title="Signature"
|
|
func (b *Bind) WithoutAutoHandling() *Bind
|
|
```
|
|
|
|
## SetParserDecoder
|
|
|
|
Allows you to configure the BodyParser/QueryParser decoder based on schema options, providing the possibility to add custom types for parsing.
|
|
|
|
```go title="Signature"
|
|
func SetParserDecoder(parserConfig fiber.ParserConfig{
|
|
IgnoreUnknownKeys bool,
|
|
ParserType []fiber.ParserType{
|
|
Customtype any,
|
|
Converter func(string) reflect.Value,
|
|
},
|
|
ZeroEmpty bool,
|
|
SetAliasTag string,
|
|
})
|
|
```
|
|
|
|
```go title="Example"
|
|
|
|
type CustomTime time.Time
|
|
|
|
// String returns the time in string format
|
|
func (ct *CustomTime) String() string {
|
|
t := time.Time(*ct).String()
|
|
return t
|
|
}
|
|
|
|
// Converter for CustomTime type with format "2006-01-02"
|
|
var timeConverter = func(value string) reflect.Value {
|
|
fmt.Println("timeConverter:", value)
|
|
if v, err := time.Parse("2006-01-02", value); err == nil {
|
|
return reflect.ValueOf(CustomTime(v))
|
|
}
|
|
return reflect.Value{}
|
|
}
|
|
|
|
customTime := fiber.ParserType{
|
|
CustomType: CustomTime{},
|
|
Converter: timeConverter,
|
|
}
|
|
|
|
// Add custom type to the Decoder settings
|
|
fiber.SetParserDecoder(fiber.ParserConfig{
|
|
IgnoreUnknownKeys: true,
|
|
ParserType: []fiber.ParserType{customTime},
|
|
ZeroEmpty: true,
|
|
})
|
|
|
|
// Example using CustomTime with non-RFC3339 format
|
|
type Demo struct {
|
|
Date CustomTime `form:"date" query:"date"`
|
|
Title string `form:"title" query:"title"`
|
|
Body string `form:"body" query:"body"`
|
|
}
|
|
|
|
app.Post("/body", func(c fiber.Ctx) error {
|
|
var d Demo
|
|
if err := c.Bind().Body(&d); err != nil {
|
|
return err
|
|
}
|
|
fmt.Println("d.Date:", d.Date.String())
|
|
return c.JSON(d)
|
|
})
|
|
|
|
app.Get("/query", func(c fiber.Ctx) error {
|
|
var d Demo
|
|
if err := c.Bind().Query(&d); err != nil {
|
|
return err
|
|
}
|
|
fmt.Println("d.Date:", d.Date.String())
|
|
return c.JSON(d)
|
|
})
|
|
|
|
// Run tests with the following curl commands:
|
|
|
|
# Body Binding
|
|
curl -X POST -F title=title -F body=body -F date=2021-10-20 http://localhost:3000/body
|
|
|
|
# Query Binding
|
|
curl -X GET "http://localhost:3000/query?title=title&body=body&date=2021-10-20"
|
|
```
|
|
|
|
## Validation
|
|
|
|
Validation is also possible with the binding methods. You can specify your validation rules using the `validate` struct tag.
|
|
|
|
Specify your struct validator in the [config](./fiber.md#structvalidator).
|
|
|
|
### Setup Your Validator in the Config
|
|
|
|
```go title="Example"
|
|
import "github.com/go-playground/validator/v10"
|
|
|
|
type structValidator struct {
|
|
validate *validator.Validate
|
|
}
|
|
|
|
// Validate method implementation
|
|
func (v *structValidator) Validate(out any) error {
|
|
return v.validate.Struct(out)
|
|
}
|
|
|
|
// Setup your validator in the Fiber config
|
|
app := fiber.New(fiber.Config{
|
|
StructValidator: &structValidator{validate: validator.New()},
|
|
})
|
|
```
|
|
|
|
### Usage of Validation in Binding Methods
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `json:"name" validate:"required"`
|
|
Age int `json:"age" validate:"gte=18,lte=60"`
|
|
}
|
|
|
|
app.Post("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().JSON(p); err != nil { // Receives validation errors
|
|
return err
|
|
}
|
|
})
|
|
```
|
|
|
|
## Default Fields
|
|
|
|
You can set default values for fields in the struct by using the `default` struct tag. Supported types:
|
|
|
|
- `bool`
|
|
- Float variants (`float32`, `float64`)
|
|
- Int variants (`int`, `int8`, `int16`, `int32`, `int64`)
|
|
- Uint variants (`uint`, `uint8`, `uint16`, `uint32`, `uint64`)
|
|
- `string`
|
|
- A slice of the above types. Use `|` to separate slice items.
|
|
- A pointer to one of the above types (**pointers to slices and slices of pointers are not supported**).
|
|
|
|
```go title="Example"
|
|
type Person struct {
|
|
Name string `query:"name,default:john"`
|
|
Pass string `query:"pass"`
|
|
Products []string `query:"products,default:shoe|hat"`
|
|
}
|
|
|
|
app.Get("/", func(c fiber.Ctx) error {
|
|
p := new(Person)
|
|
|
|
if err := c.Bind().Query(p); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println(p.Name) // john
|
|
log.Println(p.Pass) // doe
|
|
log.Println(p.Products) // ["shoe", "hat"]
|
|
|
|
// ...
|
|
})
|
|
```
|
|
|
|
Run tests with the following `curl` command:
|
|
|
|
```bash
|
|
curl "http://localhost:3000/?pass=doe"
|
|
```
|