README
¶
Package mold
Package mold is a general library to help modify or set data within data structures and other objects.
How can this help me you ask, please see the examples here
Installation
Use go get.
go get -u github.com/go-playground/mold
Then import the form package into your own code.
import "github.com/go-playground/mold"
Simple example
package main
import (
"context"
"fmt"
"log"
"reflect"
"github.com/go-playground/mold"
)
var tform *mold.Transformer
func main() {
tform = mold.New()
tform.Register("set", transformMyData)
type Test struct {
String string `mold:"set"`
}
var tt Test
err := tform.Struct(context.Background(), &tt)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", tt)
var myString string
err = tform.Field(context.Background(), &myString, "set")
if err != nil {
log.Fatal(err)
}
fmt.Println(myString)
}
func transformMyData(ctx context.Context, t *mold.Transformer, value reflect.Value, param string) error {
value.SetString("test")
return nil
}
Full example
package main
import (
"context"
"fmt"
"log"
"net/url"
"github.com/go-playground/form"
"github.com/go-playground/mold/modifiers"
"github.com/go-playground/mold/scrubbers"
"gopkg.in/go-playground/validator.v9"
)
// This example is centered around a form post, but doesn't have to be
// just trying to give a well rounded real life example.
// <form method="POST">
// <input type="text" name="Name" value="joeybloggs"/>
// <input type="text" name="Age" value="3"/>
// <input type="text" name="Gender" value="Male"/>
// <input type="text" name="Address[0].Name" value="26 Here Blvd."/>
// <input type="text" name="Address[0].Phone" value="9(999)999-9999"/>
// <input type="text" name="Address[1].Name" value="26 There Blvd."/>
// <input type="text" name="Address[1].Phone" value="1(111)111-1111"/>
// <input type="text" name="active" value="true"/>
// <input type="submit"/>
// </form>
var (
conform = modifiers.New()
scrub = scrubbers.New()
validate = validator.New()
decoder = form.NewDecoder()
)
// Address contains address information
type Address struct {
Name string `mod:"trim" validate:"required"`
Phone string `mod:"trim" validate:"required"`
}
// User contains user information
type User struct {
Name string `mod:"trim" validate:"required" scrub:"name"`
Age uint8 ` validate:"required,gt=0,lt=130"`
Gender string ` validate:"required"`
Email string `mod:"trim" validate:"required,email" scrub:"emails"`
Address []Address ` validate:"required,dive"`
Active bool `form:"active"`
}
func main() {
// this simulates the results of http.Request's ParseForm() function
values := parseForm()
var user User
// must pass a pointer
err := decoder.Decode(&user, values)
if err != nil {
log.Panic(err)
}
fmt.Printf("Decoded:%+v\n\n", user)
// great not lets conform our values, after all a human input the data
// nobody's perfect
err = conform.Struct(context.Background(), &user)
if err != nil {
log.Panic(err)
}
fmt.Printf("Conformed:%+v\n\n", user)
// that's better all those extra spaces are gone
// let's validate the data
err = validate.Struct(user)
if err != nil {
log.Panic(err)
}
// ok now we know our data is good, let's do something with it like:
// save to database
// process request
// etc....
// ok now I'm done working with my data
// let's log or store it somewhere
// oh wait a minute, we have some sensitive PII data
// let's make sure that's de-identified first
err = scrub.Struct(context.Background(), &user)
if err != nil {
log.Panic(err)
}
fmt.Printf("Scrubbed:%+v\n\n", user)
}
// this simulates the results of http.Request's ParseForm() function
func parseForm() url.Values {
return url.Values{
"Name": []string{" joeybloggs "},
"Age": []string{"3"},
"Gender": []string{"Male"},
"Email": []string{"Dean.Karn@gmail.com "},
"Address[0].Name": []string{"26 Here Blvd."},
"Address[0].Phone": []string{"9(999)999-9999"},
"Address[1].Name": []string{"26 There Blvd."},
"Address[1].Phone": []string{"1(111)111-1111"},
"active": []string{"true"},
}
}
Special Information
- To use a comma(,) within your params replace use it's hex representation instead '0x2C' which will be replaced while caching.
Contributing
I am definitly interested in the communities help in adding more scrubbers and modifiers. Please send a PR with tests, and prefereably no extra dependencies, at lease until a solid base has been built.
Complimentary Software
Here is a list of software that compliments using this library post decoding.
- validator - Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving.
- form - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
Package Versioning
I'm jumping on the vendoring bandwagon, you should vendor this package as I will not be creating different version with gopkg.in like allot of my other libraries.
Why? because my time is spread pretty thin maintaining all of the libraries I have + LIFE, it is so freeing not to worry about it and will help me keep pouring out bigger and better things for you the community.
License
Distributed under MIT License, please see license file in code for more details.
Documentation
¶
Index ¶
- Variables
- func HasValue(field reflect.Value) bool
- type ErrInvalidTag
- type ErrInvalidTransformValue
- type ErrInvalidTransformation
- type ErrUndefinedTag
- type Func
- type StructLevelFunc
- type Transformer
- func (t *Transformer) Field(ctx context.Context, v interface{}, tags string) (err error)
- func (t *Transformer) Register(tag string, fn Func)
- func (t *Transformer) RegisterAlias(alias, tags string)
- func (t *Transformer) RegisterStructLevel(fn StructLevelFunc, types ...interface{})
- func (t *Transformer) SetTagName(tagName string)
- func (t *Transformer) Struct(ctx context.Context, v interface{}) error
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidDive = errors.New("Invalid dive tag configuration")
ErrInvalidDive describes an invalid dive tag configuration
Functions ¶
Types ¶
type ErrInvalidTag ¶
type ErrInvalidTag struct {
// contains filtered or unexported fields
}
ErrInvalidTag defines a bad value for a tag being used
func (*ErrInvalidTag) Error ¶
func (e *ErrInvalidTag) Error() string
Error returns the InvalidTag error text
type ErrInvalidTransformValue ¶
type ErrInvalidTransformValue struct {
// contains filtered or unexported fields
}
An ErrInvalidTransformValue describes an invalid argument passed to Struct or Var. (The argument passed must be a non-nil pointer.)
func (*ErrInvalidTransformValue) Error ¶
func (e *ErrInvalidTransformValue) Error() string
type ErrInvalidTransformation ¶
type ErrInvalidTransformation struct {
// contains filtered or unexported fields
}
ErrInvalidTransformation describes an invalid argument passed to `Struct` or `Field`
func (*ErrInvalidTransformation) Error ¶
func (e *ErrInvalidTransformation) Error() string
Error returns ErrInvalidTransformation message
type ErrUndefinedTag ¶
type ErrUndefinedTag struct {
// contains filtered or unexported fields
}
ErrUndefinedTag defines a tag that does not exist
func (*ErrUndefinedTag) Error ¶
func (e *ErrUndefinedTag) Error() string
Error returns the UndefinedTag error text
type StructLevelFunc ¶
StructLevelFunc accepts all values needed for struct level validation
type Transformer ¶
type Transformer struct {
// contains filtered or unexported fields
}
Transformer is the base controlling object which contains all necessary information
func New ¶
func New() *Transformer
New creates a new Transform object with default tag name of 'mold'
func (*Transformer) Field ¶
func (t *Transformer) Field(ctx context.Context, v interface{}, tags string) (err error)
Field applies the provided transformations against the variable
func (*Transformer) Register ¶
func (t *Transformer) Register(tag string, fn Func)
Register adds a transformation with the given tag
NOTES: - if the key already exists, the previous transformation function will be replaced. - this method is not thread-safe it is intended that these all be registered before hand
func (*Transformer) RegisterAlias ¶
func (t *Transformer) RegisterAlias(alias, tags string)
RegisterAlias registers a mapping of a single transform tag that defines a common or complex set of transformations to simplify adding transforms to structs.
NOTE: this function is not thread-safe it is intended that these all be registered before hand
func (*Transformer) RegisterStructLevel ¶
func (t *Transformer) RegisterStructLevel(fn StructLevelFunc, types ...interface{})
RegisterStructLevel registers a StructLevelFunc against a number of types. Why does this exist? For structs for which you may not have access or rights to add tags too, from other packages your using.
NOTES: - this method is not thread-safe it is intended that these all be registered prior to any validation
func (*Transformer) SetTagName ¶
func (t *Transformer) SetTagName(tagName string)
SetTagName sets the given tag name to be used. Default is "trans"