Custom UnmarshalYAML, how to implement Unmarshaler interface on custom type

有些话、适合烂在心里 提交于 2019-12-01 01:58:52

问题


I parse a .yaml file and need to unmarshal one of its properties in a custom manner. I am using the "gopkg.in/yaml.v2" package.

The property in question is stored like this in my .yaml file:

endPointNumberSequences:
  AD1: [ 0, 10, 14, 1, 11, 2, 100, 101, 12 ]

So it is basically a map[string][]uint16 kind of type.
But I need map[string]EpnSeq where EpnSeq is defined as:
type EpnSeq map[uint16]uint16

My struct:

type CitConfig struct {
    // lots of other properties
    // ...

    EndPointNumberSequences  map[string]EpnSeq `yaml:"endPointNumberSequences"`
}

I tried to implement the Unmarshaler interface on it like this:

// Implements the Unmarshaler interface of the yaml pkg.
func (e EpnSeq) UnmarshalYAML(unmarshal func(interface{}) error) error {
    yamlEpnSequence := make([]uint16, 0)
    err := unmarshal(&yamlEpnSequence)
    if err != nil {
        return err
    }

    for priority, epn := range yamlEpnSequence {
        e[epn] = uint16(priority) // crashes with nil pointer
    }

    return nil
}

My problem is that inside the UnmarshalYAML function the EpnSeq type is not defined, causing a nil pointer exception at runtime.
How do I correctly implement the Unmarshaler interface here?


回答1:


Since @Volker did not post his comment as answer, I will do for the sake of completeness.
So I was already on the right path, but simply failed to dereference the pointer receiver of my struct, when initializing it:

// Implements the Unmarshaler interface of the yaml pkg.
func (e *EpnSeq) UnmarshalYAML(unmarshal func(interface{}) error) error {
    yamlEpnSequence := make([]uint16, 0)
    err := unmarshal(&yamlEpnSequence)
    if err != nil {
        return err
    }

    // make sure to dereference before assignment, 
    // otherwise only the local variable will be overwritten
    // and not the value the pointer actually points to
    *e = make(EpnSeq, len(yamlEpnSequence))
    for priority, epn := range yamlEpnSequence {
        e[epn] = uint16(priority) // no crash anymore
    }

    return nil
}


来源:https://stackoverflow.com/questions/49530395/custom-unmarshalyaml-how-to-implement-unmarshaler-interface-on-custom-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!