Giter VIP home page Giter VIP logo

copier's People

Contributors

azumads avatar borystomala avatar bryndin avatar chyroc avatar corpix avatar dexterp avatar driventokill avatar felixonmars avatar fyyang avatar hothero avatar jheroy avatar jiang4869 avatar jinzhu avatar juju812 avatar kcchu avatar kohago avatar kyleboyle avatar math-nao avatar matthieuzbo avatar miskolee002 avatar nicklaswallgren avatar qianchenglong avatar rahulkhairwar avatar rangelreale avatar takumin avatar tomdevelops avatar tomtwinkle avatar uded avatar winggao avatar zerosnake0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

copier's Issues

Add support for recursive copy on Struct fields

Currently, copying a struct field pointer is copying pointer. So modifications on struct source or dst affect both structs.

	type Details struct {
		Info  string
		Info2 *string
	}
	type User struct {
		Details *Details
	}

	info2 := "world"
	from := User{Details: &Details{Info: "hello", Info2: &info2}}
	to := User{}
	copier.Copy(&to, from)

	*to.Details.Info2 = "new value" // => *from.Details.Info2 is now set to "new value"

Add Support to Copy zero length Slice

res := []SampleArray{}
if err := copier.Copy(&SampleArray, sourceArray); err != nil {
	return nil, errors.Wrap(err, "failed to copy response")
}

if sourceArray is zero length array then res is nil !!

i want res is zero length array!!

[Bug] Ordering of field in Struct leads to panic

Reproducible Example

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

Description

Please look at the example code.
I can copy this struct:

type Work struct {
	ID      string  `json:"id"`
	Name    string  `json:"name"`
	UserID  *string `json:"user_id"`
	Website *string `json:"website"`
	Timestamps
}

but not this:

type NotWork struct {
	ID      string  `json:"id"`
	UserID  *string `json:"user_id"`
	Name    string  `json:"name"`
	Website *string `json:"website"`
	Timestamps
}

[Bug] Copying pointer to struct is not working

Reproducible Example

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

Description

Hi everyone,

I had several issue copying a structure to another which contain pointers.

It seems that if your structure cointain some pointer to another struct, the pointer address from the source is copied rather than building a new object and set the value of the pointer to the new instance.

So when you change the value of the destination object for instance, you will automatically change the value of the source ... which is not what I / (we ?) expect.

I shared the example here
I think that is a huge issue

Thanks in advance :) !

@jinzhu

field with same name but different type

type structSameName1 struct {
	A string
	B int64
	C time.Time
}
type structSameName2 struct {
	A string
	B time.Time
	C int64
}

obj1 := structSameName1{A: "123", B: 2, C: time.Now()}
obj2 := &structSameName2{}
err := copier.Copy(obj2, &obj1)
t.Log(err)

It will raise an error
panic: reflect: call of reflect.Value.FieldByName on int64 Value

bug report

package main

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

type Person struct {
	Name string
}

func main() {
	a := []Person{Person{Name: "Li"}}
	b := []Person{}
	err := copier.Copy(&b, &a)
	fmt.Println(err)
	fmt.Println(b)
}
source slice type unsupported
<nil>
[{Li}]

copy is successful, but err is not none.

maybe you should add "return None" after https://github.com/jinzhu/copier/blob/master/copier.go#L90

panic: reflect: call of reflect.Value.SetMapIndex on interface Value

var m = make(map[string]string)
m["a"] = "ccc"

from := []interface{}{[]int{7,8,9},2,3, m, errors.New("aaaa")}
var to []interface{}

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

from[0].([]int)[0] = 10

fmt.Println(to)

this code will panic

Copy of struct with contained slice

The implementation doesn't actually create a new slice for the copy. The test doesn't catch this because the test is also flawed. I don't understand reflect enough to attempt a fix.

The patch pasted in here fixes the test and hence surfaces the bug.

diff --git a/copier_test.go b/copier_test.go
index 977194d3..869e4e03 100644
--- a/copier_test.go
+++ b/copier_test.go
@@ -175,7 +175,9 @@ func TestAssignableTypeMethod(t *testing.T) {
 }

 func TestCopyStruct(t *testing.T) {
-       user := User{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}, flags: []byte{'x'}}
+       notes := make([]string, 0, 10)
+       notes = append(notes, "hello world")
+       user := User{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: notes, flags: []byte{'x'}}
        employee := Employee{}

        Copy(&employee, &user)

How to copy only not null fields?

Is there a way to copy only the not null fields?

Example:

package main

import (
	"fmt"

	"github.com/jinzhu/copier"
)

type Player struct {
	Firstname  string
	Username   *string
	UserDetail *UserDetail
}

type PlayerInput struct {
	Firstname  *string
	Username   *string
	UserDetail *UserDetail
}

type UserDetail struct {
	Email *string
}

func main() {
	inputFirstname := "Bob"

	input := PlayerInput{
		Firstname: &inputFirstname,
	}

	outputUsername := "BobTheBob"

	output := Player{
		Username: &outputUsername,
	}

	copier.Copy(&output, &input)

	fmt.Printf("%#v \n", output)
}

I get:

main.Player{Firstname:"Bob", Username:(*string)(nil), UserDetail:(*main.UserDetail)(nil)}

I would:

main.Player{Firstname:"Bob", Username:"BobTheBob", UserDetail:(*main.UserDetail)(nil)}

Is this possible?

Deep copy does not copy fields in the specified structure

Deep copy does not copy fields in the specified structure

In some scenarios, it is not necessary to copy all the fields.

Motivation

In the cache, data is stored with pointers. Now there is a scenario where only some fields of this data need to be removed, but the pointer content cannot be modified. Due to the complexity of data structure, only deep copy can be used.

Related Issues

apache/servicecomb-service-center#921

[bug] panic in copying slices >v0.2.0

Reproducible Example

type CollectionAlias struct {
	CollectionName string `json:"collection_name"`
	Name string `json:"name"`
}

func createNewCollectionAlias(collectionName string, name string) *api.CollectionAlias {
	return &api.CollectionAlias{
		CollectionName: collectionName,
		Name:           name,
	}
}

...

	expectedResult := []*api.CollectionAlias{
		createNewCollectionAlias("collection", "collection_alias1"),
		createNewCollectionAlias("collection", "collection_alias2"),
		createNewCollectionAlias("collection", "collection_alias3"),
	}

	mockedResult := []*api.CollectionAlias{}
	copier.Copy(&mockedResult, &expectedResult) // <--- panic here

Description

This bug is reproducible for all versions > v0.2.0

You can get more details here.

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
}

unable to copy struct with nested slices

Reproducible Example

type slice0 struct {
	sl1 []slice1
}

type slice1 struct {
	sl2 []slice2
}

type slice2 struct {
	sl2 []int
}

realdata := slice0{[]slice1{slice1{[]slice2{slice2{[]int{1, 2, 3}}}}}}
var copydata slice0
copier.Copy(&copydata, &realdata)
copydata.sl1[0] = slice1{[]slice2{slice2{[]int{10, 20, 30}}}}

Playground example
https://play.golang.org/p/drVdfl5hx7M

Description

Running above example results in error index out of range.

LICENSE missing

Hello,

This package is missing a license. Could you specify what license it has?

Most go packages just use a vanilla MIT license like this:

The MIT License (MIT)

Copyright (c) 2015 Jinzhu

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Thanks!
Ernesto

copy/pass by value versus this library

so if I have a struct:

package main

import "log"

var s = struct{Foo string}{"foo"}

func acceptStruct(a interface{}, b interface{}) bool {
	return a == b
}

func main() {
	log.Println(acceptStruct(s, &s))
}

will the first argument be copied - and how is the copy different than the deep copy that this library uses?

Update to improve doc

refs #38 - I have updated a comment to improve the clarity of the documentation, please look into it.

NumField of non-struct type

Not sure if interface{} objects are supported but I'm trying to clone a JSON object of type map[string]interface{} without success.

Here's my test:

import "mytest/copier"
import "encoding/json"
import "io/ioutil"
import "fmt"

func main() {
    var jsonObject map[string]interface{}
    data, _ := ioutil.ReadFile("./test.json")
    json.NewDecoder(data).Decode(&jsonObject)
    fmt.Println("Result:", jsonObject)
}

Output:

panic: reflect: NumField of non-struct type

goroutine 1 [running]:
panic(0x361fc0, 0xc42013abe0)
        /usr/local/Cellar/go/1.7.3/libexec/src/runtime/panic.go:500 +0x1a1
reflect.(*rtype).NumField(0x396420, 0xabdc8)
        /usr/local/Cellar/go/1.7.3/libexec/src/reflect/type.go:1003 +0x96
copier.deepFields(0x58fac0, 0x396420, 0x195, 0x58fac0, 0x396420)
        /Users/guatedude/Projects/go/src/mytest/copier/copier.go:123 +0x76
copier.Copy(0x384820, 0xc420134230, 0x384820, 0xc420134228, 0xc420131470, 0xc42012d640)
        /Users/guatedude/Projects/go/src/mytest/copier/copier.go:70 +0x3d2
main.main()
        /Users/guatedude/Projects/go/src/mytest/main.go:63 +0x11c7

Copy Nested structs and pointers panic

Like this

type Elem1 struct {
       E Elem1
       E1 int
}

type Elem2 struct {
       E Elem2
       E1 int
}

type A struct {
       B Elem1
}

type C struct {
       B Elem2
}

a := new(A)
c := new(C)
copy(c, a)

will panic

Nested structs and pointers don't get deep copied

Sample Code

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

type Outer struct {
	Inner Inner
}

type Inner struct {
	intPtr *int
}

type DriverOptions struct {
	GenOptions map[string]interface{}
}

func main() {
	intVal := 5
	outer := Outer{
		Inner: Inner{
			intPtr: &intVal,
		},
	}
	from := DriverOptions{
		GenOptions: map[string]interface{}{
			"key": outer,
		},
	}
	to := DriverOptions{}
	if err := copier.Copy(&to, &from); nil != err {
		return
	}
	*to.GenOptions["key"].(Outer).Inner.intPtr = 6
	fmt.Println(*from.GenOptions["key"].(Outer).Inner.intPtr)
}

Output

6

能提供一个自定义字段映射的功能么

Describe the feature

有两个struct的属性字段名不同,但是含义却是相同的,例如:

type User struct {
    Name string
}

type UserVo struct{
    UserName string
}

Java中类似的库orika就提供了下面的处理方案。

    mapperFactory.classMap(PersonSource.class, PersonDestination.class)
       .field("firstName", "givenName")
       .field("lastName", "sirName")
       .byDefault()
       .register();

Motivation

这种场景还是比较常见的,希望能提供类似的功能支持

Related Issues

刚发现PR中前两天正好有人提了。
Copy different field name from tag flag #86

panic when copying field with same name but different type

It's a bit similar to #17:


import (
	"log"

	"github.com/jinzhu/copier"
)

type x struct{ Name string }

type structSameName1 struct {
	A string
	B []x
}

type structSameName2 struct {
	A string
	B x
}

func main() {
	obj1 := structSameName1{A: "123", B: []x{{Name: "ee"}}}
	obj2 := &structSameName2{}
	err := copier.Copy(obj2, &obj1)
	log.Println(err)
}

Running this will lead to panic:
panic: reflect: call of reflect.Value.FieldByName on slice Value

Not sure if this is a bug, but it won't panic in an old e15f8e2. And thanks for your time on this project :)

Elements in slices can't be merged due to not convertible

As code shown as below, elements in slices aren't merged but appended due to fromType.ConvertibleTo(toType) is false.
In my view the two struct is identical expect for all fields is ptr type, and if you directly copy the struct it's working fine.

Seems like root cause is behavior of isSlice flag and if from.Kind() == reflect.Slice && to.Kind() == reflect.Slice && fromType.ConvertibleTo(toType) branch isn't consistent. But currently I don't know how to fix this. Could you please provide some clarification and help?

Thx.

type TestStruct struct {
	Name string `json:"name"`
	Number int `json:"number"`
}

type TestPtrStruct struct {
	Name *string `json:"name"`
	Number *int `json:"number"`
}

func main() {
	s := "def"

	ts := []TestStruct{{Name: "abc"}}
	tps := []TestPtrStruct{{Name: &s}}
	err := copier.Copy(&ts, &tps)
	if err != nil {
		fmt.Printf("error while copy: %v\n", err)
		return
	}

	fmt.Println(ts)

	t := TestStruct{Name: "abc"}
	tp := TestPtrStruct{Name: &s}

	err = copier.Copy(&t, &tp)
	if err != nil {
		fmt.Printf("error while copy: %v\n", err)
		return
	}

	fmt.Println(t)

}

Output:

[{abc 0} {def 0}]
{def 0}

Expected output:

[{def 0}]
{def 0}

Bug with a nested struct

Here is the setup:

type Outer struct {
	Inner Inner1
}

type Inner1 struct {
	Inner *Inner2
}

type Inner2 struct {
	Foo string
}

func TestDeepCopy(t *testing.T) {
	original := &Outer{Inner: Inner1{Inner: &Inner2{Foo: "foo"}}}
	copied := &Outer{}
	copier.Copy(copied, original)
	copied.Inner.Inner.Foo = "bar"
	assert.Equal(t, "foo", original.Inner.Inner.Foo)
}

Outer is the type that I want to copy, it has a nested struct via value: Inner1, that struct has a nested struct via pointer: *Inner2.
After coping I update the most inner field Foo in the new struct, and expect, that it won't change in the original struct. But it does change.

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 ?

Typo in readme?

In the readme, you have a "Role", and "SuperRule": is that a typo of "SuperRole"?

v.IsZero undefined

I am using your library in my project.
Compilation Errror:-
vendor/github.com/jinzhu/copier/copier.go:211:10: v.IsZero undefined (type reflect.Value has no field or method IsZero)

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:

if toField := dest.FieldByName(name); toField.IsValid() {

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.

[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)

Struct with pointers

At the moment I am unable to copy struct A to struct B.
It does not copy because this check: fromField.Type().AssignableTo(toField.Type()) on line 73 returns false. It is false because fromField type is *string and toField type is string.
Is it possible to copy these two kind of structs?

type A struct {
    Title *string
    Description *string
    Status *bool
}
type B struct {
    Title string
    Description string
    Status bool
}

addition to docs

Can you please say if there are any problem when field name on on Struct is Capital, and other (same name) starts with (small) lowercase letter.

Also, what happens with embedded fields....do they get copied too??

Feature Request

Can we have non empty values copying functionality from one struct to another. Basically it should check for zero values in the source struct, and assign to destination only when it is not empty.

Trying to copy a struct isn't working

I was trying to use the copier to copy a struct but isn't working for me. Following is the code:

https://goplay.space/#ARoaaKRtM2K

type Cat struct {
	age  int
	name string
}

func main() {
	firstCat := Cat{7, "Wilson"}
	secondCat := Cat{}
	copier.Copy(&secondCat, &firstCat)

	fmt.Println(firstCat)
	fmt.Println(secondCat)
}

I expect the output to print {7, "Wilson"} two times but it prints {7, "Wilson"} {0 }.

Copy produces an error with gorm.Model

Reproducible Example

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

Description

Running this program produces an error (expected none):

panic: reflect: Field index out of range

goroutine 1 [running]:
reflect.Value.Field(0x5e0620, 0xc0001b5c00, 0x199, 0x3, 0x5e5a00, 0xc0001b5c00, 0x199)
	/usr/local/go-faketime/src/reflect/value.go:854 +0xd9
github.com/jinzhu/copier.copier(0x5b7f40, 0xc0001b5c00, 0x5b7f40, 0xc0001b5b90, 0x0, 0x5d39a0, 0xc000113e01)
	/tmp/gopath536822222/pkg/mod/github.com/jinzhu/[email protected]/copier.go:196 +0x17cd
github.com/jinzhu/copier.Copy(...)
	/tmp/gopath536822222/pkg/mod/github.com/jinzhu/[email protected]/copier.go:35
main.main()
	/tmp/sandbox082636651/prog.go:29 +0x1ab

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.