Skip to main content

Transformation

With Fuego, you can transform data coming in and out of your application. This is useful for a variety of reasons, such as:

  • Converting data from one format to another
  • Normalizing data
  • Sanitizing data
  • Masking sensitive data
  • And more...

Input Transformation

Input transformation is the process of transforming the data coming into your application.

package main

import (
"context"
"strings"

"github.com/go-fuego/fuego"
)

type User struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}

func (u *User) InTransform(ctx context.Context) error {
u.FirstName = strings.ToUpper(u.FirstName)
u.LastName = strings.TrimSpace(u.LastName)
return nil
}

var _ fuego.InTransformer = (*User)(nil) // Ensure *User implements fuego.InTransformer
// This check is a classic example of Go's interface implementation check and we highly recommend to use it

In the example above, we have a User struct with two fields: FirstName and LastName. We also have a method called InTransform that takes a context.Context and returns an error. This method is called before the data is unmarshaled into the User struct. In this method, we are transforming the FirstName to uppercase and trimming any whitespace from the LastName.

When using the following controller, the data will be transformed before it is unmarshaled into the User struct.

func echoCapitalized(c fuego.ContextWithBody[User]) (User, error) {
user, err := c.Body()
if err != nil {
return User{}, err
}

// user.FirstName is in uppercase

return u, nil
}

Recursion

Transformation is not recursive. If you have nested structs, you will need to transform each struct individually. This is done on purpose to give you more control over the transformation process: no assumptions are made about how you want to transform your data, no "magic".

type Address struct {
Street string `json:"street"`
City string `json:"city"`
}

func (a *Address) InTransform(ctx context.Context) error {
a.Street = strings.TrimSpace(a.Street)
a.City = strings.ToUpper(a.City)
return nil
}

type User struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Address Address `json:"address"` // Nested struct
}

func (u *User) InTransform(ctx context.Context) error {
u.FirstName = strings.ToUpper(u.FirstName)
u.LastName = strings.TrimSpace(u.LastName)

err := u.Address.InTransform(ctx) // Transform the nested struct
if err != nil {
return err
}

return nil
}