Closed s1berc0de closed 9 months ago
Could you give an example? With goverter comments and your preferred solution.
Smth like this
type Input struct {
id uint64
}
func (i Input) ID() uint64 {
return i.id
}
type Output struct {
ID uint64
}
// goverter:converter
type Converter interface {
// goverter:map ID() ID
Convert(source Input) Output
}
Yeah, sounds good. I'd say goverter should automatically try to map methods to properties, so your example above should be automatically handled. Still it should be possible to manually define it, when the names on the source and target doesn't match
type Input struct {
id uint64
}
func (i Input) Identifier() uint64 {
return i.id
}
type Output struct {
ID uint64
}
// goverter:converter
type Converter interface {
// goverter:map Identifier() ID
Convert(source Input) Output
}
Exactly, method and field can't have the same names, so if goverter can't find struct field with this name, it should to search a method, and now we have one restriction that is one method parameter, I think an idea to convert multi inputs in one output also good, it's pretty good if you use domain aggreagate of few entities
Now goverter can't map fields of anonymous nested struct, dunno why, but it is
now we have one restriction that is one method parameter, I think an idea to convert multi inputs in one output also good, it's pretty good if you use domain aggreagate of few entities
Could you elaborate this with an example? I don't understand what you mean with multiple inputs.
Goverter should be able to map fields on anonymous structs, but the definition is a bit cumbersome, could you give an example that doesn't work?
About multi inputs: type EntityMixin struct { CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time ID uint64 }
type Account struct { Version time.Time ConfirmedAt sql.NullTime Email string Password string EntityMixin Status enums.AccountStatus }
type Role struct { ID uint64 Type enums.RoleType }
type Group struct { gorm.EntityMixin Name string }
// goverter:converter type Converter interface { // goverter:map accountEntity.EntityMixin.ID ID // goverter:map accountEntity.Email Email // goverter:map accountEntity.Version Version // goverter:map roleEntity.Type RoleType // goverter:map groupEntity.EntityMixin.ID GroupID DatabaseToEntities(accountEntity entities.Account, roleEntity entities.Role, groupEntity entities.Group) identity.Identity }
Error while creating converter method: ...
expected signature to have only one parameter exit status 1
About one input, but nested EntityMixin struct, entities the same as upper, but contract is:
type DatabaseToEntitiesInput struct {
AccountEntity *entities.Account
RoleEntity *entities.Role
GroupEntity *entities.Group
}
// goverter:converter
type Converter interface {
// goverter:map AccountEntity.EntityMixin.ID ID
// goverter:map AccountEntity.Email Email
// goverter:map AccountEntity.Version Version
// goverter:map RoleEntity.Type RoleType
// goverter:map GroupEntity.EntityMixin.ID GroupID
DatabaseToEntities() *identity.Identity
}
Error while creating converter method: ....
source.??? target.ID | uint64 |
---|
...
Cannot match the target field with the source entry: "ID" does not exist. exit status 1
Can't find AccountEntity.EntityMixin.ID source, EntityMixin is anonimus nested struct
Multiple inputs will probably be supported with #68 I'll keep this in mind when implementing it.
Do you mean in the second example DatabaseToEntities(*DatabaseToEntitiesInput) *identity.Identity
?
If yes, then you can use autoMap for this
// goverter:converter
type Converter interface {
// goverter:autoMap AccountEntity
// goverter:autoMap RoleEntity
// goverter:autoMap GroupEntity
DatabaseToEntities(*DatabaseToEntitiesInput) *identity.Identity
}
See https://goverter.jmattheis.de/#/conversion/mapping?id=auto-map & https://github.com/jmattheis/goverter/issues/55
autoMap doesn't work because of anonymous nested EntityMixin, still error: Cannot match the target field with the source entry: "ID" does not exist. I see it works nice if all fields have names, but here is
type EntityMixin struct { CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time ID uint64 }
type Account struct { Version time.Time ConfirmedAt sql.NullTime Email string Password string EntityMixin Status enums.AccountStatus }
Can you provide a smaller example that is self contained? You should be able to access the anonymous or rather embedded struct by the type name in your case EntityMixin in goverter. See https://github.com/jmattheis/goverter/issues/24
Yes, if i write the mapping function i can get access to the ID field through the EntityMixin, but goverter doesn't see this ability
type A struct {
ID uint64
}
type B struct {
A
Test string
}
type C struct {
ID uint64
Test string
}
type DatabaseToEntitiesInput struct {
B B
}
// goverter:converter
type Converter interface {
// goverter:autoMap B
DatabaseToEntities(*DatabaseToEntitiesInput) *C
}
Gets error too
Oh, if i don't use pointers inside of DatabaseToEntitiesInput it can map field from embedded struct
ID is on the A struct so it isn't seen by just automapping B, you need properties from both B and B.A:
// goverter:converter
type Converter interface {
// goverter:autoMap B.A
// goverter:autoMap B
DatabaseToEntities(*DatabaseToEntitiesInput) *C
}
This builds without problems.
Yeah, got now problems with mapping time.Time type
time.Time | ||||||
---|---|---|---|---|---|---|
source.AccountEntity.Version.??? target .Version.wall | uint64 | |||||||
---|---|---|---|---|---|---|---|---|
time.Time | ||||||||
type A struct { ID uint64 }
type B struct { A Version time.Time Test string }
type C struct { ID uint64 Version time.Time Test string }
type DatabaseToEntitiesInput struct { B B }
// goverter:converter type Converter interface { // goverter:map B.A.ID ID // goverter:map B.Test Test // goverter:map B.Version Version DatabaseToEntities(DatabaseToEntitiesInput) C }
goverter tries to watch inside of time.Time structure instead of copy as object
Goverter doesn't know that see https://github.com/jmattheis/goverter/issues/4
Yeah i see, thnq for the discussion, so now we have 2 features: #68 and that is in the title
Feature added in v1.1.0. Example:
Input:
package structs
// goverter:converter
type Converter interface {
Convert(source Input) Output
}
type Input struct {
Name string
}
func (Input) Age() int {
return 42
}
type Output struct {
Name string
Age int
}
Output:
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
package generated
import execution "github.com/jmattheis/goverter/execution"
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source execution.Input) execution.Output {
var structsOutput execution.Output
structsOutput.Name = source.Name
structsOutput.Age = source.Age()
return structsOutput
}
Fixes #91
I think it would be a great idea to map source structure method result to a target structure field (it can help to map private structure fields)