convert

package module
v1.2.12 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2021 License: MIT Imports: 8 Imported by: 3

README

go-convert Actions Status Coverage Status PkgGoDev GoDoc go-report

Convert a value into another type.

go get -u github.com/Eun/go-convert

Usage

package main

import (
	"fmt"

	"github.com/Eun/go-convert"
)

func main() {
	// convert a int to a string
	var s string
	convert.MustConvert(1, &s)
	fmt.Printf("%s\n", s)

	// convert a map into a struct
	type User struct {
		ID   int
		Name string
	}
	var u User
	convert.MustConvert(map[string]string{
		"Name": "Joe",
		"ID":   "10",
	}, &u)
	fmt.Printf("%#v\n", u)

	// convert Id to int and Groups to []int and keep the rest
	m := map[string]interface{}{
		"Id":     0,
		"Groups": []int{},
	}
	// convert a map into well defined map
	convert.MustConvert(
		map[string]interface{}{
			"Id":      "1",
			"Name":    "Joe",
			"Groups":  []string{"3", "6"},
			"Country": "US",
		},
		&m,
	)
	fmt.Printf("%v\n", m)

	// convert a interface slice into well defined interface slice
	// making the first one an integer, the second a string and the third an float
	sl := []interface{}{0, "", 0.0}
	convert.MustConvert([]string{"1", "2", "3"}, &sl)
	fmt.Printf("%v\n", sl)
}

Recipe system

go-convert uses a recipe system that defines how and which types should be converted in which type. A lot of recipes are already builtin (see recipes.go), however you can add your own or overwrite the builtin ones.

package main

import (
	"fmt"
	"strings"

	"github.com/Eun/go-convert"
)

type Roles struct {
	IsAdmin     bool
	IsDeveloper bool
}

type User struct {
	ID    int
	Name  string
	Roles Roles
}

func main() {
	// this is the data we want to convert
	data := map[string]string{
		"id":    "10",
		"Name":  "Joe",
		"roles": "AD", // this user is Admin (A) and Developer (D)
	}

	// create a converter
	conv := convert.New(convert.Options{
		Recipes: convert.MustMakeRecipes(
			// convert string into Roles
			func(_ convert.Converter, in string, out *Roles) error {
				(*out).IsAdmin = false
				(*out).IsDeveloper = false
				if strings.Contains(in, "A") {
					(*out).IsAdmin = true
				}
				if strings.Contains(in, "D") {
					(*out).IsDeveloper = true
				}
				return nil
			},
		),
	})

	var user User
	conv.MustConvert(data, &user)
	// user is now an instance of User
	fmt.Printf("%#v\n", user)
}

Adding inline recipes

You can also add recipes inline by implementing a ConvertRecipes() []Recipe function.
Example:

package main

import (
	"fmt"
	"strings"

	"github.com/Eun/go-convert"
)

type Roles struct {
	IsAdmin     bool
	IsDeveloper bool
}

type User struct {
	ID    int
	Name  string
	Roles Roles
}

func (user *User) ConvertRecipes() []convert.Recipe {
	return convert.MustMakeRecipes(
		// convert string into Roles
		func(_ convert.Converter, in string, out *Roles) error {
			out.IsAdmin = false
			out.IsDeveloper = false
			if strings.Contains(in, "A") {
				out.IsAdmin = true
			}
			if strings.Contains(in, "D") {
				out.IsDeveloper = true
			}
			return nil
		},
	)
}

func main() {
	// this is the data we want to convert
	data := []map[string]string{
		{
			"id":    "10",
			"Name":  "Joe",
			"roles": "AD", // this user is Admin (A) and Developer (D)
		},
		{
			"id":    "21",
			"Name":  "Alice",
			"roles": "D", // this user is Developer (D)
		},
	}

	var users []User
	convert.MustConvert(data, &users)
	// users is now an instance of []User
	fmt.Printf("%#v\n", users)
}

Notice

This library is using reflection so be aware it might be slow in your usecase.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var MapType = reflect.TypeOf((*MapValue)(nil)).Elem()

MapType can be used to specify a recipe with the source/destination with a map type

View Source
var NilType = reflect.TypeOf((*NilValue)(nil)).Elem()

NilType can be used to specify a recipe with the source/destination with a nil value

View Source
var SliceType = reflect.TypeOf((*SliceValue)(nil)).Elem()

SliceType can be used to specify a recipe with the source/destination with a slice type

View Source
var StructType = reflect.TypeOf((*StructValue)(nil)).Elem()

StructType can be used to specify a recipe with the source/destination with a struct type

Functions

func Convert

func Convert(src, dst interface{}, options ...Options) error

Convert converts the specified value to the specified type. The behavior can be influenced by using the options

Example:

var str string
if err := Convert(8, &str); err != nil {
    panic(err)
}
fmt.Printf("%s\n", str)
Example
// Convert a map of strings to a struct

// this is the struct we want to convert to
type User struct {
	ID   int
	Name string
}

// this is the data we want to convert
data := map[string]string{
	"id":   "10",
	"Name": "Joe",
}

var user User
// do the conversion
convert.MustConvert(data, &user)

fmt.Printf("Hello %s, your ID is %d\n", user.Name, user.ID)
Output:

func ConvertReflectValue

func ConvertReflectValue(src, dstTyp reflect.Value, options ...Options) error

ConvertReflectValue converts the specified reflect value to the specified type The behavior can be influenced by using the options

func MustConvert

func MustConvert(src, dst interface{}, options ...Options)

MustConvert calls Convert() but panics if there is an error

func MustConvertReflectValue

func MustConvertReflectValue(src, dstTyp reflect.Value, options ...Options)

MustConvertReflectValue calls MustConvertReflectValue() but panics if there is an error

Types

type ConvertRecipes

type ConvertRecipes interface {
	ConvertRecipes() []Recipe
}

ConvertRecipes can be used to add recipes to a type in a convenient way

type Converter

type Converter interface {
	Options() *Options
	Convert(src, dst interface{}, options ...Options) error
	MustConvert(src, dst interface{}, options ...Options)
	ConvertReflectValue(src, dst reflect.Value, options ...Options) error
	MustConvertReflectValue(src, dst reflect.Value, options ...Options)
}

Converter is the instance that will be used to convert values

func New

func New(options ...Options) Converter

New creates a new converter that can be used multiple times

Example
type Roles struct {
	IsAdmin     bool
	IsDeveloper bool
}

type User struct {
	ID    int
	Name  string
	Roles Roles
}

// this is the data we want to convert
data := map[string]string{
	"id":    "10",
	"Name":  "Joe",
	"roles": "AD", // this user is Admin (A) and Developer (D)
}

// create a converter
conv := convert.New(convert.Options{
	SkipUnknownFields: false,
	Recipes: convert.MustMakeRecipes(
		// convert string into Roles
		func(_ convert.Converter, in string, out *Roles) error {
			out.IsAdmin = false
			out.IsDeveloper = false
			if strings.Contains(in, "A") {
				out.IsAdmin = true
			}
			if strings.Contains(in, "D") {
				out.IsDeveloper = true
			}
			return nil
		},
	),
})

var user User
conv.MustConvert(data, &user)
// user is now an instance of User
fmt.Printf("%#v\n", user)
Output:

type MapValue

type MapValue struct {
	reflect.Value
}

MapValue represents a map value to convert (from/to)

type NilValue

type NilValue struct {
	reflect.Value
}

NilValue represents a nil value to convert (from/to)

type Options

type Options struct {
	// SkipUnknownFields can be used to ignore fields that are not existent in the destination type
	//
	// Example:
	//     type User struct {
	//         Name string
	//     }
	//     m := map[string]interface{}{
	//         "Name":     "Joe",
	//         "Surname":  "Doe",
	//     }
	//     // convert a map into User type
	//     var user User
	//     // will fail because Surname is not in the User struct
	//     MustConvert(m, &user)
	//     // will pass
	//     MustConvert(m, &user, Options{SkipUnknownFields: true})
	SkipUnknownFields bool
	// Recipes can be used to define custom recipes for this converter
	Recipes []Recipe
}

Options can be used to alter the behavior of the converter

type Recipe

type Recipe struct {
	From reflect.Type
	To   reflect.Type
	Func func(c Converter, in reflect.Value, out reflect.Value) error
}

Recipe represents a recipe that defines which type can be converted into which type and which function should be called to convert this type

func MakeRecipe

func MakeRecipe(fn interface{}) (Recipe, error)

MakeRecipe makes a recipe for the passed in function.

Note that the functions must match this format:

func(Converter, INVALUE, *OUTVALUE) (error)

Example:

// convert int to bool
MakeRecipe(func(c Converter, in int, out *bool) error {
    if in == 0 {
        *out = false
        return nil
    }
    *out = true
    return nil
})

func MakeRecipes

func MakeRecipes(f ...interface{}) ([]Recipe, error)

MakeRecipes makes a recipe slice for the passed in functions. see also MakeRecipe

func MustMakeRecipe

func MustMakeRecipe(f interface{}) Recipe

MustMakeRecipe makes a recipe for the passed in functions, but panics on error. see also MakeRecipe

func MustMakeRecipes

func MustMakeRecipes(f ...interface{}) []Recipe

MustMakeRecipes makes a recipe slice for the passed in functions, but panics on error. see also MakeRecipe

type SliceValue

type SliceValue struct {
	reflect.Value
}

SliceValue represents a slice value to convert (from/to)

type StructValue

type StructValue struct {
	reflect.Value
}

StructValue represents a struct value to convert (from/to)

Directories

Path Synopsis
examples
internal

Jump to

Keyboard shortcuts

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