Code Monkey home page Code Monkey logo

mapper's Introduction

devfeel/mapper

A simple and easy go tools for auto mapper struct to map, struct to struct, slice to slice, map to slice, map to json.

1. Install

go get -u github.com/devfeel/mapper

2. Getting Started

Traditional Usage

package main

import (
	"fmt"
	"github.com/devfeel/mapper"
)

type (
	User struct {
		Name string
		Age  int
		Id   string `mapper:"_id"`
		AA   string `json:"Score"`
		Time time.Time
	}

	Student struct {
		Name  string
		Age   int
		Id    string `mapper:"_id"`
		Score string
	}

	Teacher struct {
		Name  string
		Age   int
		Id    string `mapper:"_id"`
		Level string
	}
)

func init() {
	mapper.Register(&User{})
	mapper.Register(&Student{})
}

func main() {
	user := &User{}
	userMap := &User{}
	teacher := &Teacher{}
	student := &Student{Name: "test", Age: 10, Id: "testId", Score: "100"}
	valMap := make(map[string]interface{})
	valMap["Name"] = "map"
	valMap["Age"] = 10
	valMap["_id"] = "x1asd"
	valMap["Score"] = 100
	valMap["Time"] = time.Now()

	mapper.Mapper(student, user)
	mapper.AutoMapper(student, teacher)
	mapper.MapperMap(valMap, userMap)

	fmt.Println("student:", student)
	fmt.Println("user:", user)
	fmt.Println("teacher", teacher)
	fmt.Println("userMap:", userMap)
}

执行main,输出:

student: &{test 10 testId 100}
user: &{test 10 testId 100 0001-01-01 00:00:00 +0000 UTC}
teacher &{test 10 testId }
userMap: &{map 10 x1asd 100 2017-11-20 13:45:56.3972504 +0800 CST m=+0.006004001}

Object Usage

package main

import (
  "fmt"
  "github.com/devfeel/mapper"
)

type (
  User struct {
    Name  string `json:"name" mapper:"name"`
    Class int    `mapper:"class"`
    Age   int    `json:"age" mapper:"-"`
  }

  Student struct {
    Name  string `json:"name" mapper:"name"`
    Class int    `mapper:"class"`
    Age   []int  `json:"age" mapper:"-"`
  }
)

func main() {
  user := &User{Name: "shyandsy", Class: 1, Age: 10}
  student := &Student{}

  // create mapper object
  m := mapper.NewMapper()

  // in the version < v0.7.8, we will use field name as key when mapping structs
  // we keep it as default behavior in this version
  m.SetEnableIgnoreFieldTag(true)

  student.Age = []int{1}

  // disable the json tag
  m.SetEnabledJsonTag(false)

  // student::age should be 1
  m.Mapper(user, student)

  fmt.Println("user:")
  fmt.Println(user)
  fmt.Println("student:")
  fmt.Println(student)
}

执行main,输出:

user:
&{shyandsy 1 10}
student:
&{shyandsy 1 [1]}

Features

  • 支持不同结构体相同名称相同类型字段自动赋值,使用Mapper
  • 支持不同结构体Slice的自动赋值,使用MapperSlice
  • 支持字段为结构体时的自动赋值
  • 支持struct到map的自动映射赋值,使用Mapper
  • 支持map到struct的自动映射赋值,使用MapperMap
  • 支持map到struct slice的自动赋值,使用MapToSlice
  • 支持map与json的互相转换
  • 支持Time与Unix自动转换
  • 支持tag标签,tag关键字为 mapper
  • 兼容json-tag标签
  • 当tag为"-"时,将忽略tag定义,使用struct field name
  • 无需手动Register struct,内部自动识别
  • 支持开启关闭
    • SetEnabledTypeChecking(bool) // 类型检查
    • IsEnabledTypeChecking
    • SetEnabledMapperTag // mapper tag
    • IsEnabledMapperTag
    • SetEnabledJsonTag // json tag
    • IsEnabledJsonTag
    • SetEnabledAutoTypeConvert // auto type convert
    • IsEnabledAutoTypeConvert
    • SetEnabledMapperStructField // mapper struct field
    • IsEnabledMapperStructField

mapper's People

Contributors

devfeel avatar mrwormhole avatar shyandsy avatar zhangmingfeng 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

mapper's Issues

mapper.AutoMapper不支持struct嵌入

package test

import (
	"encoding/json"
	"github.com/devfeel/mapper"
	"testing"
)
type SysConfig1 struct{
SysConfigBase1
Foundation string
Reward uint64
GenesisHash []byte
}
type SysConfigBase1 struct{
	Amount uint64
	Token string
}
type SysConfig2 struct{
	SysConfigBase2
	Reward uint64
	Foundation string
	GenesisHeight int
}
type SysConfigBase2 struct{
	Amount uint64
	Token string
	Total uint64
}
func TestAutoMapper(t *testing.T){
	config1:=&SysConfig1{
		SysConfigBase1: SysConfigBase1{Amount:10000000,Token:"PTN"},
		Foundation:     "TestFoundation",
		Reward:1500000,
		GenesisHash:    []byte("Genesis"),
	}
	data,_:= json.Marshal(config1)
	t.Logf("config1:%s",string(data))
	config2:=&SysConfig2{}
	mapper.AutoMapper(config1, config2)
	data,_= json.Marshal(config2)
	t.Logf("config2:%s",string(data))
}

以上代码,运行结果为:

 mapper_test.go:37: config1:{"Amount":10000000,"Token":"PTN","Foundation":"TestFoundation","Reward":1500000,"GenesisHash":"R2VuZXNpcw=="}
mapper_test.go:41: config2:{"Amount":0,"Token":"","Total":0,"Reward":1500000,"Foundation":"TestFoundation","GenesisHeight":0}

显然SysConfigBase1中的数据没有映射过来。

不支持 struct 中带有struct 以及struct slice

func ExampleMap_2() {

type ItemStruct1 struct {
	ProductId int64
}
type ItemStruct2 struct {
	ProductId int64
}
type ProductBasic struct {
	ProductId    int64
	CategoryType int 
	ProductTitle string
	item         ItemStruct1
}
type ProductGetResponse struct {
	// ProductBasic;
	ProductId    int64
	CategoryType int
	ProductTitle string
	item         ItemStruct2
}
basic := &ProductBasic{
	ProductId:    10001,
	CategoryType: 1,
	ProductTitle: "fdsffdsf待",
	item:         ItemStruct1{ProductId: 20},
}
response := &ProductGetResponse{}
mapper.AutoMapper(basic, response)
fmt.Println(response)
// output:20

}

proposal: support mapping between pointer and value

I plan to make a new feature to support mapping between pointer and value

example:

type A struct{
    Age int `mapper:"age"`
}

type B struct{
    Age *int `mapper:"age"`
} 

func main(){
    a := A{Age:1}
    b := B{}
    m := mapper.NewMapper()

    m.Mapper(&a, &b)

    // now b.Age = 1
}

Can not map an an aray of struct to another

I am trying to map an array of struct to another array.
`package main

import (
"fmt"

"github.com/devfeel/mapper"

)

type Emp struct {
Name string
Class int
}
type Emp2 struct {
FirstName string mapper:"Name"
Class int
}

func main() {
e1 := Emp{Name: "Ajit", Class: 1}

var e2 Emp2
if err := mapper.Mapper(&e1, &e2); err != nil {
	fmt.Println(err)
}
fmt.Printf("e1:= %v", e1)
fmt.Printf("e2:= %v", e2)
e2 = Emp2{}
a1 := []Emp{
	Emp{Name: "Ajit", Class: 1},
	Emp{Name: "vinit", Class: 2},
}
var a2 []Emp
if err := mapper.Mapper(&a1, &a2); err != nil {
	fmt.Println(err)
}
fmt.Printf("a1:= %v", a1)
fmt.Printf("a2:= %v", a2)

}`

But it results in panic
`7:31:44 app | panic: reflect: call of reflect.Value.NumField on slice Value

goroutine 1 [running]:
reflect.flag.mustBe(...)
/usr/local/Cellar/go/1.13.1/libexec/src/reflect/value.go:208
reflect.Value.NumField(0x10cdba0, 0xc00000c080, 0x197, 0x11194e0)
/usr/local/Cellar/go/1.13.1/libexec/src/reflect/value.go:
7:31:44 app | 1356 +0xbe
github.com/devfeel/mapper.registerValue(0x10cdba0, 0xc00000c080, 0x197, 0x1044900, 0x1055610)
/Users/d069900/go/src/github.com/devfeel/mapper/mapper.go:116 +0x30f
github.com/devfeel/mapper.elemMapper(0x10cdba0, 0xc00000c080
7:31:44 app | , 0x197, 0x10cdba0, 0xc00000c0a0, 0x197, 0xd, 0x10)
/Users/d069900/go/src/github.com/devfeel/mapper/mapper.go:299 +0xbb2
github.com/devfeel/mapper.Mapper(0x10c9880, 0xc00000c080, 0x10c9880, 0xc00000c0a0
7:31:44 app | , 0xc000084ef0, 0x1)
/Users/d069900/go/src/github.com/devfeel/mapper/mapper.go:254 +0x1c1
main.main()
/Users/d069900/rnd/go/go-school/src/object-mappers/main.go:33 +0x369
`

Issue 1: it must only return error and not panic
issue 2: arrays are not mapped

Mapper doesn't work on composition

I have this models that wants to map a slice of Country to a slice of CountryRes

Source:

// Base model
type BaseModel struct {
	Id    int    `json:"id"`
}

// Country model
type Country struct {
	BaseModel
	Name string `json:"name"`
}

//
type CountryRes struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}

When I want to map a slice of Country to a slice of CountryRes the Id field has been ignored.

var items *[]Country = new([]Country)
var mitems *[]CountryRes = new([]CountryRes)
err = mapper.MapperSlice(items, mitems) 

The execution didn't have any errors but the Id field had been ignored.

Caching for reflection

Question: Do we do caching to not repeat reflection for each mapper call for structs?

Can't mapper between the slice

package main

import (
	"fmt"

	"github.com/devfeel/mapper"
)
type User struct {
	ID   int64  `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

type User2 struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func main() {
	users := []*User{
		{
			ID:   1,
			Name: "baozi",
			Age:  12,
		},
		{
			ID:   2,
			Name: "de",
			Age:  13,
		},
	}

	user2s := make([]*User2, 0)
	err := mapper.AutoMapper(users, &user2s)
	if err != nil {
		fmt.Printf("错误:%v", err)
		return
	}
	for k, v := range user2s {
		fmt.Printf("%d的结构体:%+v", k, v)
	}
	fmt.Println("hello world")
}

em.........

The result is : panic: reflect: call of reflect.Value.Elem on slice Value
probable cause: github.com/devfeel/mapper/mapper.go:152 +0x64

can you help me ? thanks 👍

嵌套

不支持嵌套?可以参考下这个项目 :
github.com/fatih/structs

MapperSlice

type UserInfo struct {
//Name string gorm:"name"
//Sex int gorm:"sex"
//Age int gorm:"age"
//Phone string gorm:"phone"

Name string
//Sex  int
Age      int
Phone    string
PassWord string

}

type UserListOutPutDto struct {
Name string
Age int
Phone string
}
当我给output加 json标识的时候
数组无法转换成功

Optional json Tag

Can using json tag being optional? Default is true, but can we set the json tag to false. Something like this:

mapper.SetUsingJsonTag(false)

It's quite uncomfortable when I want to use field name but overwrited by json tag. I need to overwrite again with mapper tag.
Thank you. This project is really great helper to develop really fast.

泛型支持?

试用了一下,非常棒哟,是否有考虑如下模式?
e.g.

m := mapper.NewMapper()

result := m.mapper[T](&orgrigin_data)

println(result)
...

[BUG] MapperSlice panics while mapping from *[] to *[]

if i have two different structs, i can not use both of their pointers in MapperSlice function.

this works
mapper.MapperSlice(highscores, &highscoresResponse)

this doesn't work and panics in the runtime(this should be supported in my opinion)
mapper.MapperSlice(&highscores, &highscoresResponse)

this doesn't work obviously which is normal(source code states toElem has to be pointer)
mapper.MapperSlice(highscores, highscoresResponse)

There should be a mechanism to improve for the second option. Should i open a PR for this?

这种情况怎么转?

type Temp struct {
ObjectId int64 json:"objectId" form:"objectId" gorm:"primaryKey;column:object_id;comment:base-主键;type:bigint"
Name string json:"name" form:"name" gorm:"column:name;comment:名称;"
Value int64 json:"value" form:"value" gorm:"column:value;comment:值;"
}

val := []model.Temp{
model.Temp{1, "1", 11},
model.Temp{2, "2", 12},
model.Temp{3, "3", 13},
}
m := model.Data{
TblName: "test",
Data: val,
}
bytes, _ := json.Marshal(m)

n := new(model.Data)
err := json.Unmarshal(bytes, n)
if err != nil {
	t.Fatal(err)
}

arr := make([]model.Temp, 0)
mapper.Register(&model.Temp{})
if err := mapper.MapperSlice(n.Data, arr); err != nil {
	fmt.Println(arr)
} else {
	t.Error("错误")
}

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.