问题
I encountered an issue while trying to unmarshal a struct with an unexported field using github.com/go-yaml/yaml
. The struct looks like:
type Example struct {
ExportedField string `yaml:"exported-field"`
OneMoreExported string `yaml:"one-more-exported"`
unexportedField map[string]*AnotherExample `yaml:"unexported-field"`
}
type AnotherExample struct {
Name string `yaml:"name"`
}
And I'd like to unmarshal such YAML as
exported-field: lorem ipsum
one-more-exported: dolor set
unexported-field:
something:
name: anything
What I tried is a custom unmarshaler:
func (example *Example) UnmarshalYAML(unmarshal func(interface{}) error) error {
type Alias Example
tmp := struct {
UnexportedField map[string]*AnotherExample `yaml:"unexported-field"`
*Alias
}{
Alias: (*Alias)(example),
}
if err := unmarshal(&tmp); err != nil {
return err
}
if tmp.UnexportedField != nil {
example.unexportedField = tmp.UnexportedField
}
example.CopyJobNonNil(Example(*tmp.Alias)) // Copies all the non-nil fields from the passed Example instance
return nil
}
tmp
after calling unmarshal()
doesn't contain any fields but unexportedField — other fields seems to be omitted.
The reproduced issue on Go Playground (although it isn't working due to the dependencies): https://play.golang.org/p/XZg7tEPGXna
回答1:
Because most Go unmarshalling packages (including the encoding/*
packages) use the reflect
package to get at struct fields, and reflect
can't access unexported struct fields, the unmarshaler can't parse into unexported fields.
That said, there is still a way to do it. You can unmarshall the YAML into an an unexported type with public fields, which can then be embedded into an exported type. Getters and setters in the same package can just use the embedded struct.
For example:
// Define the types...
type innerData struct {
ExportedField string
unexportedField string
}
type Data struct {
innerData
}
// and then...
d := Data{}
DoSomeUnmarshalling(yamlbytes, &d.innerData)
// and then you can use getters/setters/whatever on `Data`
func (d *Data) GetUnexported() string {
return d.innerData.unexportedField;
}
(warning: completely untested)
See JSON and dealing with unexported fields for reference.
来源:https://stackoverflow.com/questions/48674624/unmarshal-a-yaml-to-a-struct-with-unexpected-fields-in-go