I have struct as below:
type Connect struct {
ClientID string `yaml:"clientid"`
Password string `yaml:"password"`
Timeout time.Duration `yaml:"timeout"`
}
c1 := `
id: 'client1'
password: 'hhhhhhha'
timeout: 10
`
c2 := `
id: 'client2'
password: 'llllllla'
timeout: '10'
`
c3 := `
id: 'client3'
password: 'hhhhhhha'
timeout: 10s
`
c4 := `
id: 'client4'
password: 'llllllla'
timeout: '10s'
`
as shown above, type of Timeout is time.Duration, the default unit is Nanosecond, but I want to get the result: c1 && c2 has error, c3 && c4 is valid(the config of Timeout must have unit). How should I do to rewrite the UnmarshalYAML() Method for yaml? Thanks a lot.
I would create an aliased type in the UnmarshalYAML
function so that all the values could be unmarshaled to some primitive types. Then I will rewrite those values that match and convert those which do not:
package main
import (
"fmt"
"time"
"gopkg.in/yaml.v2"
)
type Connect struct {
ClientID string `yaml:"clientid"`
Password string `yaml:"password"`
Timeout time.Duration `yaml:"timeout"`
}
func (ut *Connect) UnmarshalYAML(unmarshal func(interface{}) error) error {
type alias struct {
ClientID string `yaml:"clientid"`
Password string `yaml:"password"`
Timeout string `yaml:"timeout"`
}
var tmp alias
if err := unmarshal(&tmp); err != nil {
return err
}
t, err := time.ParseDuration(tmp.Timeout)
if err != nil {
return fmt.Errorf("failed to parse '%s' to time.Duration: %v", tmp.Timeout, err)
}
ut.ClientID = tmp.ClientID
ut.Password = tmp.Password
ut.Timeout = t
return nil
}
func main() {
c1 := `
id: 'client1'
password: 'hhhhhhha'
timeout: 10
`
c2 := `
id: 'client2'
password: 'llllllla'
timeout: '10'
`
c3 := `
id: 'client3'
password: 'hhhhhhha'
timeout: 10s
`
c4 := `
id: 'client4'
password: 'llllllla'
timeout: '10s'
`
cc := []string{c1, c2, c3, c4}
for i, cstr := range cc {
var c Connect
err := yaml.Unmarshal([]byte(cstr), &c)
if err != nil {
fmt.Printf("Error for c%d: %v\n", (i + 1), err)
continue
}
fmt.Printf("c%d: %+v\n", (i + 1), c)
}
}
The output looks as follows:
$ go run main.go
Error for c1: failed to parse '10' to time.Duration: time: missing unit in duration10
Error for c2: failed to parse '10' to time.Duration: time: missing unit in duration10
c3: {ClientID: Password:hhhhhhha Timeout:10s}
c4: {ClientID: Password:llllllla Timeout:10s}