# Data Binding and Validation

Middlware binding provides request data binding and validation for Macaron [Instances](/core_concepts.md#instances).

* [GitHub](https://github.com/go-macaron/binding)
* [API Reference](https://gowalker.org/github.com/go-macaron/binding)

## Installation

```bash
go get github.com/go-macaron/binding
```

## Usage

### Getting form data from a request

Suppose you have a contact form on your site where at least name and message are required. We'll need a struct to receive the data:

```go
type ContactForm struct {
    Name           string `form:"name" binding:"Required"`
    Email          string `form:"email"`
    Message        string `form:"message" binding:"Required"`
    MailingAddress string `form:"mailing_address"`
}
```

Then we simply add our route in Macaron:

```go
m.Post("/contact/submit", binding.Bind(ContactForm{}), func(contact ContactForm) string {
    return fmt.Sprintf("Name: %s\nEmail: %s\nMessage: %s\nMailing Address: %v",
        contact.Name, contact.Email, contact.Message, contact.MailingAddress)
})
```

That's it! The [`binding.Bind`](https://gowalker.org/github.com/go-macaron/binding#Bind) function takes care of validating required fields.

By default, if there are any errors (like a required field is empty), binding middleware will return an error to the client and your app won't even see the request. To prevent this behavior, you can use [`binding.BindIgnErr`](https://gowalker.org/github.com/go-macaron/binding#BindIgnErr) instead.

{% hint style="danger" %}
Don't try to bind to embedded struct pointers; it won't work. See [martini-contrib/binding issue 30](https://github.com/martini-contrib/binding/issues/30) if you want to help with this.
{% endhint %}

#### Naming Convention

By default, there is one naming convention for form tag name, which are:

* `Name` -> `name`
* `UnitPrice` -> `unit_price`

For example, previous example can be simplified with following code:

```go
type ContactForm struct {
    Name           string `binding:"Required"`
    Email          string
    Message        string `binding:"Required"`
    MailingAddress string
}
```

Clean and neat, isn't it?

If you want to custom your app naming convention, you can use [`binding.SetNameMapper`](https://gowalker.org/github.com/go-macaron/binding#SetNameMapper) function, which accepts a function that is type of [`binding.NameMapper`](https://gowalker.org/github.com/go-macaron/binding#NameMapper).

### Getting JSON data from a request

To get data from JSON payloads, simply use the `json:` struct tags instead of `form:`.

{% hint style="info" %}
Use [JSON-to-Go](http://mholt.github.io/json-to-go/) to correctly convert JSON to a Go type definition. It's useful if you're new to this or the structure is large/complex.
{% endhint %}

### Binding to interfaces

If you'd like to bind the data to an interface rather than to a concrete struct, you can specify the interface and use it like this:

```go
m.Post("/contact/submit", binding.Bind(ContactForm{}, (*MyInterface)(nil)), func(contact MyInterface) {
    // ... your struct became an interface!
})
```

## Description of Handlers

Each of these middleware handlers are independent and optional, though be aware that some handlers invoke other ones.

### Bind

[`binding.Bind`](https://gowalker.org/github.com/go-macaron/binding#Bind) is a convenient wrapper over the other handlers in this package. It does the following boilerplate for you:

1. Deserializes request data into a struct
2. Performs validation with [`binding.Validate`](https://gowalker.org/github.com/go-macaron/binding#Validate)
3. If your struct doesn't implement [`binding.ErrorHandler`](https://gowalker.org/github.com/go-macaron/binding#ErrorHandler), then default error handling will be applied. Otherwise, calls `ErrorHandler.Error` method to perform custom error handling.

Notes:

* Your application (the final handler) will not even see the request if there are any errors when default error handling is applied.
* Header `Content-Type` will be used to know how to deserialize the requests.

{% hint style="danger" %}
Don't attempt to bind a pointer to a struct. This will cause a panic [to prevent a race condition](https://github.com/codegangsta/martini-contrib/pull/34#issuecomment-29683659) where every request would be pointing to the same struct.
{% endhint %}

### Form

[`binding.Form`](https://gowalker.org/github.com/go-macaron/binding#Form) deserializes form data from the request, whether in the query string or as a `form-urlencoded` payload. It only does these things:

1. Deserializes request data into a struct
2. Performs validation with [`binding.Validate`](https://gowalker.org/github.com/go-macaron/binding#Validate)

Note that it does not handle errors. You may receive a [`binding.Errors`](https://gowalker.org/github.com/go-macaron/binding#Errors) into your own handler if you want to handle errors.

### MultipartForm and File Uploads

Like [`binding.Form`](https://gowalker.org/github.com/go-macaron/binding#Form), [`binding.MultipartForm`](https://gowalker.org/github.com/go-macaron/binding#MultipartForm) deserializes form data from a request into the struct you pass in. Additionally, this will deserialize a POST request that has a form of `enctype="multipart/form-data"`. If the bound struct contains a field of type [`*multipart.FileHeader`](http://gowalker.org/pkg/mime/multipart/#FileHeader) (or `[]*multipart.FileHeader`), you also can read any uploaded files that were part of the form.

This handler does the following:

1. Deserializes request data into a struct
2. Performs validation with [`binding.Validate`](https://gowalker.org/github.com/go-macaron/binding#Validate)

Again, like [`binding.Form`](https://gowalker.org/github.com/go-macaron/binding#Form), no error handling is performed, but you can get the errors in your handler by receiving a [`binding.Errors`](https://gowalker.org/github.com/go-macaron/binding#Errors) type.

#### Example

```go
type UploadForm struct {
    Title      string                `form:"title"`
    TextUpload *multipart.FileHeader `form:"txtUpload"`
}

func main() {
    m := macaron.Classic()
    m.Post("/", binding.MultipartForm(UploadForm{}), uploadHandler(uf UploadForm) string {
        file, err := uf.TextUpload.Open()
        // ... you can now read the uploaded file
    })
    m.Run()
}
```

### Json

[`binding.Json`](https://gowalker.org/github.com/go-macaron/binding#Json) deserializes JSON data in the payload of the request. It does the following things:

1. Deserializes request data into a struct
2. Performs validation with [`binding.Validate`](https://gowalker.org/github.com/go-macaron/binding#Validate)

Similar to [`binding.Form`](https://gowalker.org/github.com/go-macaron/binding#Form), no error handling is performed, but you can get the errors and handle them yourself.

### Validate

[`binding.Validate`](https://gowalker.org/github.com/go-macaron/binding#Validate) receives a populated struct and checks it for errors with basic rules. It will execute the `Validator.Validate()` method on the struct, if it is a [`binding.Validator`](https://gowalker.org/github.com/go-macaron/binding#Validator).

#### Validation Rules

There are some builtin validation rules. To use them, the tag format is `binding:"<Name>"`.

| Name               | Note                                                                                         |
| ------------------ | -------------------------------------------------------------------------------------------- |
| `OmitEmpty`        | Omit rest of validations if value is empty                                                   |
| `Required`         | Must be non-zero value                                                                       |
| `AlphaDash`        | Must be alpha characters or numerics or `-_`                                                 |
| `AlphaDashDot`     | Must be alpha characters or numerics, `-_` or `.`                                            |
| `Size(int)`        | Fixed length                                                                                 |
| `MinSize(int)`     | Minimum length                                                                               |
| `MaxSize(int)`     | Maximum length                                                                               |
| `Range(int,int)`   | Value range(inclusive)                                                                       |
| `Email`            | Must be E-mail address                                                                       |
| `Url`              | Must be HTTP/HTTPS URL address                                                               |
| `In(a,b,c,...)`    | Must be one of element in array                                                              |
| `NotIn(a,b,c,...)` | Must not be one of element in array                                                          |
| `Include(string)`  | Must contain                                                                                 |
| `Exclude(string)`  | Must not contain                                                                             |
| `Default(string)`  | Set default value when field is zero-value(cannot use this when bind with interface wrapper) |

To combine multiple rules: `binding:"Required;MinSize(10)"`.

## Customize Operations

### Custom Validation

If you want additional validation beyond just checking required fields, your struct can implement the [`binding.Validator`](https://gowalker.org/github.com/go-macaron/binding#Validator) interface like so:

```go
func (cf ContactForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
    if strings.Contains(cf.Message, "Go needs generics") {
        errs = append(errors, binding.Error{
            FieldNames:     []string{"message"},
            Classification: "ComplaintError",
            Message:        "Go has generics. They're called interfaces.",
        })
    }
    return errs
}
```

Now, any contact form submissions with "Go needs generics" in the message will return an error explaining your folly.

### Custom Validation Rules

If you need to more validation rules that are applied automatically for you, you can add custom rules by function [`binding.AddParamRule`](https://gowalker.org/github.com/go-macaron/binding#AddParamRule), it accepts type [`binding.ParamRule`](https://gowalker.org/github.com/go-macaron/binding#ParamRule) as argument.

Suppose you want to limit minimum value:

```go
binding.AddParamRule(&binding.ParamRule{
    IsMatch: func(rule string) bool {
        return strings.HasPrefix(rule, "Min(")
    },
    IsValid: func(errs binding.Errors, rule, name string, v interface{}) (bool, binding.Errors) {
        num, ok := v.(int)
        if !ok {
            return false, errs
        }
        min, _ := strconv.Atoi(rule[4 : len(rule)-1])
        if num < min {
            errs.Add([]string{name}, "MinimumValue", "Value is too small")
            return false, errs
        }
        return true, errs
    },
})
```

If your rule is simple, you can also use [`binding.AddRule`](https://gowalker.org/github.com/go-macaron/binding#AddRule), it accepts type [`binding.Rule`](https://gowalker.org/github.com/go-macaron/binding#Rule):

```go
binding.AddRule(&binding.Rule{
    IsMatch: func(rule string) bool {
        return rule == "String"
    },
    IsValid: func(errs binding.Errors, name string, v interface{}) (bool, binding.Errors) {
        _, ok := v.(string)
        return ok, errs
    },
})
```

Custom validation rules are applied after builtin rules.

### Custom Error Handler

If you want to avoid default error handle process but still want binding middleware calls handle function for you, your struct can implement the [`binding.ErrorHandler`](https://gowalker.org/github.com/go-macaron/binding#ErrorHandler) interface like so:

```go
func (cf ContactForm) Error(ctx *macaron.Context, errs binding.Errors) {
    // Custom process to handle error.
}
```

This operation happens after your custom validation.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://go-macaron.com/middlewares/binding.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
