goverter
goverter copied to clipboard
mapping consts
Hi Jannis, this is part question, part feature request, part "should I write this?".
If my target field should be set to a const, how would I do that? For example:
const ageOfConsent = 18
type Input struct {
Name string
}
type Output struct {
Name2 string
Age int
}
Desired field mappings:
Input.Name -> OutPut.Name2
ageOfConsent -> Output.Age
I was wondering if I should attempt to write this (as a feature), but I'd be interested in your ideas. Here's a possible syntax:
// goverter:converter
type Converter interface {
// goverter:const ageOfConsent:Age
Convert(source Input) Output
}
Hey Sonia,
currently it should be possible to extend with a custom the converter with a custom method and set all the required fields and the missing one.
Regardless, I think a similar feature could improve the usage of this library a lot. I feel like a constant is too restricting.I propose something similar to the existing goverter:extend
, but instead it targets the property of a struct.
type Input struct { Name string }
type Output struct { Name string; Age int }
// goverter:converter
type Converter interface {
// goverter:mapExtend Age DefaultAge
Convert(source Input) Output
}
func DefaultAge() int {
return 18
}
At first glance, this may seem like a more verbose version of your proposal, but the benefit is that is can cover much more use-cases. F.ex, we could allow passing the source object into this function, then the /example/error could be improved. Currently, it works like this:
// goverter:converter
// goverter:extend ToAPIPerson
type Converter interface {
ToAPIApartment(source DBApartment) APIApartment
}
func ToAPIPerson(value DBPerson) APIPerson {
return APIPerson{
ID: value.ID,
FullName: fmt.Sprintf("%s %s", value.FirstName, value.LastName),
}
}
We define an extension function for the whole *Person object. With the new goverter:mapExtend
it could be written like this:
// goverter:converter
type Converter interface {
ToAPIApartment(source DBApartment) APIApartment
// goverter:mapExtend FullName GetFullName
ToAPIPerson(source DBPerson) APIPerson
}
func GetFullName(value DBPerson) string {
return fmt.Sprintf("%s %s", value.FirstName, value.LastName)
}
This looks much better.
You could even use it to convert values, without the need to write the entire custom extension method.
type Input struct {
Percent100Based float64
// ... other fields
}
type Output struct {
Percent1Based float64
// ... other fields
}
// goverter:converter
type Converter interface {
// goverter:mapExtend Percent1Based DivideBy100
ToOutput(source Input) Output
}
func DivideBy100(source Input) float64 {
return source.Percent100Based / 100
}
The first step would be to add goverter:mapExtend
with support for only defining a method without arguments and one return value, which must be the same as the return type of the parameter that is defined inside goverter:mapExtend
. The optional passing of the source value as first parameter should be done later. Maybe we could even allow passing a Converter instance, like it can be done in goverter:extend
(https://github.com/jmattheis/goverter#reuse-generated-converter)
Also, I'm not fully satisfied with the name goverter:mapExtend
maybe you've something better?
@soniah This is possible to do in copygen:
- Use the const as a parameter for the conversion method directly OR
- Use the
map
directive: example OR - Use customized functions OR
- Use converter functions, etc.
Thanks @switchupcb that looks good. Sorry @jmattheis I haven't had time to work on the stuff above - work, family, etc...