Copier for golang, copy value from struct to struct and more

Overview

Copier

I am a copier, I copy everything from one to another

test status

Features

  • Copy from field to field with same name
  • Copy from method to field with same name
  • Copy from field to method with same name
  • Copy from slice to slice
  • Copy from struct to slice
  • Copy from map to map
  • Enforce copying a field with a tag
  • Ignore a field with a tag
  • Deep Copy

Usage

package main

import (
	"fmt"
	"github.com/jinzhu/copier"
)

type User struct {
	Name string
	Role string
	Age  int32

	// Explicitly ignored in the destination struct.
	Salary   int
}

func (user *User) DoubleAge() int32 {
	return 2 * user.Age
}

// Tags in the destination Struct provide instructions to copier.Copy to ignore
// or enforce copying and to panic or return an error if a field was not copied.
type Employee struct {
	// Tell copier.Copy to panic if this field is not copied.
	Name      string `copier:"must"`

	// Tell copier.Copy to return an error if this field is not copied.
	Age       int32  `copier:"must,nopanic"`

	// Tell copier.Copy to explicitly ignore copying this field.
	Salary    int    `copier:"-"`

	DoubleAge int32
	EmployeId int64
	SuperRole string
}

func (employee *Employee) Role(role string) {
	employee.SuperRole = "Super " + role
}

func main() {
	var (
		user      = User{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 200000}
		users     = []User{{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 100000}, {Name: "jinzhu 2", Age: 30, Role: "Dev", Salary: 60000}}
		employee  = Employee{Salary: 150000}
		employees = []Employee{}
	)

	copier.Copy(&employee, &user)

	fmt.Printf("%#v \n", employee)
	// Employee{
	//    Name: "Jinzhu",           // Copy from field
	//    Age: 18,                  // Copy from field
	//    Salary:150000,            // Copying explicitly ignored
	//    DoubleAge: 36,            // Copy from method
	//    EmployeeId: 0,            // Ignored
	//    SuperRole: "Super Admin", // Copy to method
	// }

	// Copy struct to slice
	copier.Copy(&employees, &user)

	fmt.Printf("%#v \n", employees)
	// []Employee{
	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeId: 0, SuperRole: "Super Admin"}
	// }

	// Copy slice to slice
	employees = []Employee{}
	copier.Copy(&employees, &users)

	fmt.Printf("%#v \n", employees)
	// []Employee{
	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeId: 0, SuperRole: "Super Admin"},
	//   {Name: "jinzhu 2", Age: 30, Salary:0, DoubleAge: 60, EmployeId: 0, SuperRole: "Super Dev"},
	// }

 	// Copy map to map
	map1 := map[int]int{3: 6, 4: 8}
	map2 := map[int32]int8{}
	copier.Copy(&map2, map1)

	fmt.Printf("%#v \n", map2)
	// map[int32]int8{3:6, 4:8}
}

Copy with Option

copier.CopyWithOption(&to, &from, copier.Option{IgnoreEmpty: true, DeepCopy: true})

Contributing

You can help to make the project better, check out http://gorm.io/contribute.html for things you can do.

Author

jinzhu

License

Released under the MIT License.

Issues
  • Copy with nested pointer to struct causes panic

    Copy with nested pointer to struct causes panic

    The following code causes a panic:

    package main
    
    import "github.com/jinzhu/copier"
    
    func main() {
    	type nested struct {
    		A string
    	}
    	type parentA struct {
    		*nested
    	}
    	type parentB struct {
    		*nested
    	}
    	a := parentA{nested: &nested{A: "a"}}
    	b := parentB{}
    
    	copier.Copy(&b, &a)
    }
    
    

    stack trace:

    $ go run copier_panic.go
    panic: reflect: indirection through nil pointer to embedded struct
    
    goroutine 1 [running]:
    reflect.Value.FieldByIndex(0x4d4fe0, 0xc04206e020, 0x199, 0xc0420500d0, 0x2, 0x2, 0x0, 0x568f40, 0x4c8a00)
            C:/tools/go/src/reflect/value.go:804 +0x276
    reflect.Value.FieldByName(0x4d4fe0, 0xc04206e020, 0x199, 0x4b5ea6, 0x1, 0x4c8a00, 0xc042044250, 0x198)
            C:/tools/go/src/reflect/value.go:820 +0x16e
    github.com/jinzhu/copier.Copy(0x4c2a60, 0xc04206e020, 0x4c2a20, 0xc04206e018, 0x0, 0x0)
            E:/workspace/golang/src/github.com/jinzhu/copier/copier.go:71 +0x491
    main.main()
            E:/workspace/golang/src/playground/copier_panic.go:18 +0xb1
    exit status 2
    

    The issue originates from this: https://github.com/jinzhu/copier/blob/db4671f3a9b8df855e993f7c94ec5ef1ffb0a23b/copier.go#L71

    Is this something that can be fixed in copier? I don't know enough about reflection but if you can guide me, I can make a PR to fix this.

    opened by sudo-suhas 7
  • Nested Slice getting copied by reference.

    Nested Slice getting copied by reference.

    Issue demonstrated in following code snippet.

    package main
    
    import (
    	"fmt"
    	"github.com/jinzhu/copier"
    )
    
    type A struct {
    	X []int
    }
    
    type B struct {
    	X []int
    }
    
    func main() {
    	x := []int{1, 50}
    	a := A{X: x}
    	b := B{}
    	copier.Copy(&b, a)
    	fmt.Printf("X0 in B %v %v\n", b.X[0], b.X[1]) // Returns 1
    	fmt.Printf("X0 in A %v %v\n", a.X[0], a.X[1]) // Returns 1
    	a.X[0] = -1
    	a.X[1] = -50
    	fmt.Printf("X in B %v %v\n", b.X[0], b.X[1]) // Returns -1
    	fmt.Printf("X in A %v %v\n", a.X[0], a.X[1]) // Returns -1
    }
    
    
    opened by bhupkasUber 7
  • Full support sql.Null* structs on both sides. Copy to Scanner interface and from Valuer interface.

    Full support sql.Null* structs on both sides. Copy to Scanner interface and from Valuer interface.

    Right copy of:

    sql.Null* -> generic types

    • sql.NullString -> string
    • sql.NullTime -> time.Time
    • etc...

    sql.Null* -> ptr to generic types

    • sql.NullString -> *string
    • etc...

    Or vice versa:

    generic types -> sql.Null*

    • string -> sql.NullString
    • time.Time -> sql.NullTime
    • etc...

    ptr to generic types -> sql.Null*

    • *string -> sql.NullString
    • *time.Time -> sql.NullTime
    • etc...

    Totally covered by tests.

    opened by timsolov 4
  • No map support?

    No map support?

    Does not make copy of map. Example: https://play.golang.org/p/C3nwT2W9BNs

    opened by ShyLionTjmn 4
  • Added utility function CopyNonEmpty() that ignores empty fields in a struct while copying

    Added utility function CopyNonEmpty() that ignores empty fields in a struct while copying

    Implementation for 36. Added a function CopyNonEmpty(), which copies only the non-zero fields for different data types.

    opened by rahulkhairwar 4
  • [Bug] Panic on SetMapIndex when using map[x]interface{}

    [Bug] Panic on SetMapIndex when using map[x]interface{}

    Reproducible Example

    https://play.golang.org/p/RJOgBhY1oGo

    Description

    Hi everyone,

    I'm facing again a panic using the CopyWithOptions() method. See above the example.

    It seems this is related to map[x]interface{} @jinzhu

    opened by maeglindeveloper 4
  • Deepcopy handle shallow-copyable un-exported fields

    Deepcopy handle shallow-copyable un-exported fields

    Alternative to #103 without special handling for time.Time

    opened by BatmanAoD 4
  • Add support for deep copy on struct field

    Add support for deep copy on struct field

    Closes #61

    Change details:

    • Add support for deep copy when it is a struct field
    • Add more tests for this use case
    opened by math-nao 4
  • [Bug] crashed with nested struct

    [Bug] crashed with nested struct

    Reproducible Example

    https://play.golang.org/p/INvrWLUd6BD

    code samples

    package main
    
    import (
    	"github.com/jinzhu/copier"
    )
    
    func main() {
    	type Basic struct {
    		ID   int
    		Name string
    		Addr string
    	}
    
    	type S struct {
    		Basic
    		Level int
    	}
    
    	s1 := S{}
    
    	var s2 S
    	copier.Copy(&s2, s1)
    
    }
    
    

    Description

    Crashed with nested struct. seemed cause by copier.go+193.

    if f, ok := dest.Type().FieldByName(name); ok {
    for idx, x := range f.Index {
    	destFieldKind := dest.Field(x).Kind()
    

    as mentioned by: https://golang.org/pkg/reflect/#StructField

    " Index []int // index sequence for Type.FieldByIndex ", the index can't used by dest.Field(x)

    opened by tubzby 4
  • is this does not copy embeded struct ?

    is this does not copy embeded struct ?

    hi dear,

    i have some struct like this

    type BaseModel struct {
        ID        uint       `json:"id" gorm:"primary_key"`
        CreatedAt time.Time  `json:"createdAt"`
        UpdatedAt time.Time  `json:"updatedAt"`
        DeletedAt *time.Time `json:"deletedAt"`
    }
    
    // PostResource post resource
    type PostResource struct {
        BaseModel
        Title       string `json:"title"`
        Description string `json:"description"`
        // Tags        []Tag  `json:"tags"`
    }
    
    // Post post model
    type Post struct {
        BaseModel
        UserID      int    `json:"-"`
        ImageID     int    `json:"-"`
        TagID       int    `json:"-"`
        Hit         int    `json:"hit"`
        Title       string `json:"title"`
        Slug        string `json:"slug"`
        Description string `json:"description"`
        Body        string `json:"body"`
        User        User   `json:"user"`
        Tags        []Tag  `gorm:"many2many:pivot_tip_tag;"`
    }
    

    i am trying copy Post to PostResource, but the BaseModel fields(ID,CreatedAt,UpdatedAt,DeletedAt) not copying.

    do you have any idea ?

    opened by alioygur 3
  • Add support to copy from a nil slice pointer to a slice field when DeepCopy is enabled

    Add support to copy from a nil slice pointer to a slice field when DeepCopy is enabled

    Closes #118

    Change details:

    Add support to copy from a nil slice pointer to a slice field when DeepCopy is enabled Add more tests for this use case Fix typo error in previous tests

    opened by math-nao 0
  • Add support to copy from a nil slice pointer to a slice field when DeepCopy is enabled

    Add support to copy from a nil slice pointer to a slice field when DeepCopy is enabled

    Reproducible Example

    https://play.golang.org/p/H5N5ppK3vjY

    package main
    
    import "log"
    import "github.com/jinzhu/copier"
    
    func main() {
            type Sample1 struct {
    		Foobar *[]string
    	}
    	type Sample2 struct {
    		Foobar []string
    	}
    
    	from := Sample1{}
    	to := Sample2{}
    	err := copier.CopyWithOption(&to, from, copier.Option{
    		DeepCopy: true,
    	})
    	log.Printf("DeepCopy enabled, err: %v", err)
    	
    	err = copier.Copy(&to, from)
    	log.Printf("DeepCopy disabled, err: %v", err)
    
    	log.Printf("from: %v", from)
    	log.Printf("to: %v", to)
    }
    
    Output:
    2009/11/10 23:00:00 DeepCopy enabled, err: copy from is invalid
    2009/11/10 23:00:00 DeepCopy disabled, err: <nil>
    2009/11/10 23:00:00 from: {<nil>}
    2009/11/10 23:00:00 to: {[]}
    
    

    Description

    An error is triggered when copying a nil slice pointer to a slice field with DeepCopy, all following fields are not copied due to previous error.

    opened by math-nao 0
  • Copy map with slice-type value panic

    Copy map with slice-type value panic

    Reproducible Example

    fromMap := make(map[string][]int32)
    slice := []int32{1, 2}
    fromMap["key1"] = slice
    toMap := make(map[string][]int32)
    copier.Copy(&toMap, fromMap)
    

    Description

    copy a map which has slice-type value will report error: reflect.Value.Addr of unaddressable value

    opened by studentliying 0
  • fixed copy fields breaking on unexported pointer field, close #102

    fixed copy fields breaking on unexported pointer field, close #102

    unexported empty pointer fields could break the copy cycle, this PR fixes that.

    Credits go to @demobin8, for pointing this out in the issue #102 and for the solution.

    opened by tomdevelops 0
  • added converter option for type conversions

    added converter option for type conversions

    You can add now converter functions as an option, to convert type A to to type B.

    I took some inspiration from PR #90, but implemented it a little bit diffrent. Some of the diffrences are as follows:

    • passed it as an option
    • no instances
    • no exposure of reflect package
    • no external module dependencies

    Example

    func main() {
    	type SrcStruct struct {
    		Field1 time.Time
    		Field2 *time.Time
    	}
    
    	type DestStruct struct {
    		Field1 string
    		Field2 string
    	}
    
    	testTime := time.Date(2021, 3, 5, 1, 30, 0, 123000000, time.UTC)
    
    	src := SrcStruct{
    		Field1: testTime,
    		Field2: &testTime,
    	}
    
    	var dst DestStruct
    
    	err := copier.CopyWithOption(&dst, &src, copier.Option{
    		IgnoreEmpty: true,
    		DeepCopy:    true,
    		Converters: []copier.TypeConverter{
    			{
    				SrcType: time.Time{},
    				DstType: copier.String,
    				Fn: func(src interface{}) (interface{}, error) {
    					s, ok := src.(time.Time)
    
    					if !ok {
    						return nil, errors.New("src type not matching")
    					}
    
    					return s.Format(time.RFC3339), nil
    				},
    			},
    		},
    	})
    
    	if err != nil {
    		log.Fatal(err)
    	}
    	
    	// DestStruct{Field1:"2021-03-05T01:30:00Z", Field2:"2021-03-05T01:30:00Z"}
    	fmt.Printf("%#v", dst)
    }
    

    Feel free to make suggestions to any part of the PR.

    opened by tomdevelops 0
  • 小功能添加

    小功能添加

    • 增加功能
    1. 添加source flag的支持 #112
    2. 支持自定义tag标签和分割符

    删除内容:

    1. 去除getFieldName 无意义逻辑
    opened by i-curve 0
  • Copy un-exported struct fields in DeepCopy

    Copy un-exported struct fields in DeepCopy

    This should fix issues #97 and #98. Like PR #105, it is not specific to time.Time, but resolves the issue by ensuring un-exported fields of a struct are copied, even when DeepCopy: true.

    The idea was inspired by PR #105, but the structure is quite different. PR #105 did not resolve the issue I faced or make tests pass. This PR does both.

    I retained the tests added by PRs #103 and #105 and added a few more cases that exhibit the specific issue I faced.

    opened by joshhardy 1
  • Ignore copy from the source structure

    Ignore copy from the source structure

    https://github.com/jinzhu/copier/blob/c72a821a0be1f70e87a87a98ea15f3771ac0461e/copier.go#L22-L23 Can we add another tag to ignore copy from the source structure? It's possible that the destination structure is in another package which is not in our control.

    opened by miluChen 0
  • Support copying unexported fields

    Support copying unexported fields

    Describe the feature

    I would like to have copier support copying to/from unexported fields. e.g., it would be nice if this correctly copied everything: https://play.golang.org/p/VJCuOmRasov

    If there is some Go-level restriction to this, consider allowing users to define their own copy implementations for the type (e.g. look for a Copy() method on types which is invoked by the library), or something like that).

    Motivation

    Sometimes for type design I do not want to export some field, but I still want to support deep-copying it.

    Related Issues

    opened by Carrotman42 1
  • Does not create deep copy

    Does not create deep copy

    https://play.golang.org/p/IYQlesIxpD1

    Trying to deep copy a slice of struct but it is not working as all the copies are pointing to original and thus changing the copy affects the original

    opened by debasish-mihup 0
Owner
Jinzhu
Life is Art
Jinzhu
Steampipe plugin to query your Scalingo apps, addons and more

Scalingo plugin for Steampipe Use SQL to query infrastructure including applications and addons from Scalingo. Get started → Documentation: Table defi

François de Metz 9 Nov 23, 2021
💪 Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more.

?? Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more. Go 的一些工具函数,格式化,特殊处理,常用信息获取等等

Gookit 432 Dec 2, 2021
Robust & Easy to use struct mapper and utility methods for Go

go-model Robust & Easy to use model mapper and utility methods for Go struct. Typical methods increase productivity and make Go development more fun ?

Jeevanandam M. 329 Nov 24, 2021
reflect api without runtime reflect.Value cost

reflect2 reflect api that avoids runtime reflect.Value cost reflect get/set interface{}, with type checking reflect get/set unsafe.Pointer, without ty

Modern Go Programming 505 Nov 23, 2021
Helm plugin to reference value files packaged in dependency charts

Helm Octopus Plugin This Helm plugin allows to reference packaged value files (other than the default values.yaml). Install helm plugin install https:

Softonic 3 Sep 23, 2021
A Runtime Struct Builder for Go

A Runtime Struct Builder for Go

null 32 Dec 4, 2021
Go tool to modify struct field tags

Go tool to modify/update field tags in structs. gomodifytags makes it easy to update, add or delete the tags in a struct field. You can easily add new tags, update existing tags (such as appending a new key, i.e: db, xml, etc..) or remove existing tags

Fatih Arslan 1.6k Dec 6, 2021
Go linter to check the struct literal to use field name

Structfield Find struct literals using non-labeled fields. The structfield analysis reports the usage of struct literal using non-labeled fields more

Nuruddin Ashr 3 Aug 23, 2021
gin struct controller

gin struct controller

null 1 Oct 4, 2021
Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package.

Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package. The library allows you to call Go service methods from PHP with a minimal footprint, structures and []byte support.

Spiral Scout 1.1k Nov 29, 2021
A Go (golang) library for parsing and verifying versions and version constraints.

go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version can sort a collection of versions properly, handles prerelease/beta versions, can increment versions, etc.

HashiCorp 990 Nov 29, 2021
memresolver is an in-memory golang resolver that allows to override current golang Lookup func literals

mem-resolver memresolver is an in-memory golang resolver that allows to override current golang Lookup func literals How to use it Create your custom

Antonio Ojea 3 Nov 25, 2021
Code Generation for Functional Programming, Concurrency and Generics in Golang

goderive goderive derives mundane golang functions that you do not want to maintain and keeps them up to date. It does this by parsing your go code fo

Walter Schulze 937 Nov 30, 2021
Extremely flexible golang deep comparison, extends the go testing package, tests HTTP APIs and provides tests suite

go-testdeep Extremely flexible golang deep comparison, extends the go testing package. Latest news Synopsis Description Installation Functions Availab

Maxime Soulé 233 Nov 30, 2021
A well tested and comprehensive Golang statistics library package with no dependencies.

Stats - Golang Statistics Package A well tested and comprehensive Golang statistics library / package / module with no dependencies. If you have any s

Montana Flynn 2.2k Dec 2, 2021
Golang io.Reader and io.Writer but with limits

LimitIO io.Reader and io.Writer with limit.

LI Zhennan 66 Nov 18, 2021
Cogger is a standalone binary and a golang library that reads an internally tiled geotiff

Cogger is a standalone binary and a golang library that reads an internally tiled geotiff (optionally with overviews and masks) and rewrites it

Airbus DS GEO S.A. 37 Nov 15, 2021
A Golang and Python solution for Queue-it's Proof-of-Work challenge.

Queue-it Proof-of-Work A Golang and Python solution for Queue-it's Proof-of-Work challenge (https://queue-it.com/blog/proof-of-work-block-bad-bots/).

eta 15 Nov 22, 2021
⚙️ Concept of Golang HTML render engine with frontend components and dynamic behavior

SSC Engine An HTML render engine concept that brings frontend-like components experience to the server side with native html/template on steroids. Sup

Yurii Zinets 382 Dec 1, 2021