Compare commits
1 Commits
name_gener
...
mapper/v0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f48c7373d7 |
74
mapper/enum_converter.go
Normal file
74
mapper/enum_converter.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package mapper
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
type EnumTypeConverter[DTO ~string, MODEL ~int32] struct {
|
||||
nameMap map[int32]string
|
||||
valueMap map[string]int32
|
||||
}
|
||||
|
||||
func NewEnumTypeConverter[DTO ~string, MODEL ~int32](nameMap map[int32]string, valueMap map[string]int32) *EnumTypeConverter[DTO, MODEL] {
|
||||
return &EnumTypeConverter[DTO, MODEL]{
|
||||
valueMap: valueMap,
|
||||
nameMap: nameMap,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EnumTypeConverter[DTO, MODEL]) ToModel(dto *DTO) *MODEL {
|
||||
if dto == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
find, ok := m.valueMap[string(*dto)]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
model := MODEL(find)
|
||||
return &model
|
||||
}
|
||||
|
||||
func (m *EnumTypeConverter[DTO, MODEL]) ToDto(model *MODEL) *DTO {
|
||||
if model == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
find, ok := m.nameMap[int32(*model)]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
dto := DTO(find)
|
||||
return &dto
|
||||
}
|
||||
|
||||
func (m *EnumTypeConverter[DTO, MODEL]) NewConverterPair() []copier.TypeConverter {
|
||||
srcType := MODEL(0)
|
||||
dstType := DTO("")
|
||||
|
||||
fromFn := m.ToDto
|
||||
toFn := m.ToModel
|
||||
|
||||
return NewGenericTypeConverterPair(&srcType, &dstType, fromFn, toFn)
|
||||
}
|
||||
|
||||
func NewGenericTypeConverterPair[A interface{}, B interface{}](srcType A, dstType B, fromFn func(src A) B, toFn func(src B) A) []copier.TypeConverter {
|
||||
return []copier.TypeConverter{
|
||||
{
|
||||
SrcType: srcType,
|
||||
DstType: dstType,
|
||||
Fn: func(src interface{}) (interface{}, error) {
|
||||
return fromFn(src.(A)), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
SrcType: dstType,
|
||||
DstType: srcType,
|
||||
Fn: func(src interface{}) (interface{}, error) {
|
||||
return toFn(src.(B)), nil
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
20
mapper/go.mod
Normal file
20
mapper/go.mod
Normal file
@@ -0,0 +1,20 @@
|
||||
module github.com/tx7do/go-utils/mapper
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.24.3
|
||||
|
||||
require github.com/jinzhu/copier v0.4.0
|
||||
|
||||
require github.com/stretchr/testify v1.10.0
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/tx7do/go-utils => ../
|
||||
25
mapper/go.sum
Normal file
25
mapper/go.sum
Normal file
@@ -0,0 +1,25 @@
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
10
mapper/interface.go
Normal file
10
mapper/interface.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package mapper
|
||||
|
||||
// Mapper defines the interface for converting between DTOs and models.
|
||||
type Mapper[DTO any, MODEL any] interface {
|
||||
// ToModel converts a DTO to a MODEL.
|
||||
ToModel(*DTO) *MODEL
|
||||
|
||||
// ToDto converts a MODEL to a DTO.
|
||||
ToDto(*MODEL) *DTO
|
||||
}
|
||||
51
mapper/mapper.go
Normal file
51
mapper/mapper.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package mapper
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
type CopierMapper[DTO any, MODEL any] struct {
|
||||
copierOption copier.Option
|
||||
}
|
||||
|
||||
func NewCopierMapper[DTO any, MODEL any]() *CopierMapper[DTO, MODEL] {
|
||||
return &CopierMapper[DTO, MODEL]{
|
||||
copierOption: copier.Option{
|
||||
Converters: []copier.TypeConverter{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *CopierMapper[DTO, MODEL]) AppendConverter(converter copier.TypeConverter) {
|
||||
m.copierOption.Converters = append(m.copierOption.Converters, converter)
|
||||
}
|
||||
|
||||
func (m *CopierMapper[DTO, MODEL]) AppendConverters(converters []copier.TypeConverter) {
|
||||
m.copierOption.Converters = append(m.copierOption.Converters, converters...)
|
||||
}
|
||||
|
||||
func (m *CopierMapper[DTO, MODEL]) ToModel(dto *DTO) *MODEL {
|
||||
if dto == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var model MODEL
|
||||
if err := copier.CopyWithOption(&model, dto, m.copierOption); err != nil {
|
||||
panic(err) // Handle error appropriately in production code
|
||||
}
|
||||
|
||||
return &model
|
||||
}
|
||||
|
||||
func (m *CopierMapper[DTO, MODEL]) ToDto(model *MODEL) *DTO {
|
||||
if model == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var dto DTO
|
||||
if err := copier.CopyWithOption(&dto, model, m.copierOption); err != nil {
|
||||
panic(err) // Handle error appropriately in production code
|
||||
}
|
||||
|
||||
return &dto
|
||||
}
|
||||
93
mapper/mapper_test.go
Normal file
93
mapper/mapper_test.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package mapper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCopierMapper(t *testing.T) {
|
||||
type DtoType struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
type ModelType struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
mapper := NewCopierMapper[DtoType, ModelType]()
|
||||
|
||||
// 测试 ToModel 方法
|
||||
dto := &DtoType{Name: "Alice", Age: 25}
|
||||
model := mapper.ToModel(dto)
|
||||
assert.NotNil(t, model)
|
||||
assert.Equal(t, "Alice", model.Name)
|
||||
assert.Equal(t, 25, model.Age)
|
||||
|
||||
// 测试 ToModel 方法,传入 nil
|
||||
modelNil := mapper.ToModel(nil)
|
||||
assert.Nil(t, modelNil)
|
||||
|
||||
// 测试 ToDto 方法
|
||||
model = &ModelType{Name: "Bob", Age: 30}
|
||||
dtoResult := mapper.ToDto(model)
|
||||
assert.NotNil(t, dtoResult)
|
||||
assert.Equal(t, "Bob", dtoResult.Name)
|
||||
assert.Equal(t, 30, dtoResult.Age)
|
||||
|
||||
// 测试 ToDto 方法,传入 nil
|
||||
dtoNil := mapper.ToDto(nil)
|
||||
assert.Nil(t, dtoNil)
|
||||
}
|
||||
|
||||
func TestEnumTypeConverter(t *testing.T) {
|
||||
type DtoType string
|
||||
type ModelType int32
|
||||
|
||||
const (
|
||||
DtoTypeOne DtoType = "One"
|
||||
DtoTypeTwo DtoType = "Two"
|
||||
)
|
||||
|
||||
const (
|
||||
ModelTypeOne ModelType = 1
|
||||
ModelTypeTwo ModelType = 2
|
||||
)
|
||||
|
||||
nameMap := map[int32]string{
|
||||
1: "One",
|
||||
2: "Two",
|
||||
}
|
||||
valueMap := map[string]int32{
|
||||
"One": 1,
|
||||
"Two": 2,
|
||||
}
|
||||
|
||||
converter := NewEnumTypeConverter[DtoType, ModelType](nameMap, valueMap)
|
||||
|
||||
// 测试 ToModel 方法
|
||||
dto := DtoTypeOne
|
||||
model := converter.ToModel(&dto)
|
||||
assert.NotNil(t, model)
|
||||
assert.Equal(t, int32(1), int32(*model))
|
||||
|
||||
// 测试 ToModel 方法,传入不存在的值
|
||||
dtoInvalid := DtoType("Three")
|
||||
modelInvalid := converter.ToModel(&dtoInvalid)
|
||||
assert.Nil(t, modelInvalid)
|
||||
|
||||
// 测试 ToDto 方法
|
||||
tmpModelTwo := ModelTypeTwo
|
||||
model = &tmpModelTwo
|
||||
dtoResult := converter.ToDto(model)
|
||||
assert.NotNil(t, dtoResult)
|
||||
assert.Equal(t, "Two", string(*dtoResult))
|
||||
|
||||
// 测试 ToDto 方法,传入不存在的值
|
||||
tmpModelThree := ModelType(3)
|
||||
modelInvalid = &tmpModelThree
|
||||
dtoInvalidResult := converter.ToDto(modelInvalid)
|
||||
assert.Nil(t, dtoInvalidResult)
|
||||
}
|
||||
Reference in New Issue
Block a user