mold

package module
v2.2.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 13, 2017 License: MIT Imports: 8 Imported by: 4

README

Package mold

Project status Build Status Coverage Status Go Report Card GoDoc License

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 gopkg.in/go-playground/mold.v2

Then import the form package into your own code.

import "gopkg.in/go-playground/mold.v2"

Simple example

package main

import (
	"context"
	"fmt"
	"log"
	"reflect"

	"gopkg.in/go-playground/mold.v2"
)

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"

	"gopkg.in/go-playground/mold.v2/modifiers"
	"gopkg.in/go-playground/mold.v2/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.

License

Distributed under MIT License, please see license file in code for more details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidDive describes an invalid dive tag configuration
	ErrInvalidDive = errors.New("Invalid dive tag configuration")

	// ErrUndefinedKeysTag describes an undefined keys tag when and endkeys tag defined
	ErrUndefinedKeysTag = errors.New("'" + endKeysTag + "' tag encountered without a corresponding '" + keysTag + "' tag")

	// ErrInvalidKeysTag describes a misuse of the keys tag
	ErrInvalidKeysTag = errors.New("'" + keysTag + "' tag must be immediately preceeded by the '" + diveTag + "' tag")
)

Functions

func HasValue

func HasValue(field reflect.Value) bool

HasValue determines if a reflect.Value is it's default value

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 Func

type Func func(ctx context.Context, t *Transformer, value reflect.Value, param string) error

Func defines a transform function for use.

type StructLevelFunc

type StructLevelFunc func(ctx context.Context, t *Transformer, value reflect.Value) error

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"

func (*Transformer) Struct

func (t *Transformer) Struct(ctx context.Context, v interface{}) error

Struct applies transformations against the provided struct

Directories

Path Synopsis
_examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL