Как маршалировать структуру, как если бы это была анонимная структура?
В документации указано:
Поля анонимных структур обычно маршалируются так, как если бы их внутренние экспортируемые поля были полями внешней структуры.
Например:
type foo struct {
Foo1 string `json:"foo1"`
Foo2 string `json:"foo2"`
}
type boo struct {
Boo1 string `json:"boo1"`
foo
}
и я делаю это:
s := boo{
Boo: "boo1",
foo: foo{
Foo1: "foo1",
Foo2: "foo2",
},
}
b, err := json.MarshalIndent(s, "", " ")
fmt.Println(string(b))
Я получаю это:
{
"boo1": "boo1",
"foo1": "foo1",
"foo2": "foo2"
}
Но как добиться того же результата, если foo не является анонимной структурой? Значение:
type boo struct {
Boo string `json:"boo"`
Foo foo
}
А также распаковать файл json.
1 ответ
Вы должны реализовать пользовательскийjson.Marshaler
для этого.
type boo struct {
Boo1 string `json:"boo1"`
// "-" will tell encoding/json to ignore this field during (un)marshaling
Foo foo `json:"-"`
}
func (b boo) MarshalJSON() ([]byte, error) {
// Declare a new type using boo's definition, this
// "copies" boo's structure but not its behaviour,
// i.e. B has same fields as boo, but zero methods,
// not even MarshalJSON -- this is necessary to avoid
// infinite recursive calls to MarshalJSON.
type B boo
// Declare a new type that *embeds* those structs whose
// fields you want to be at the same level.
type T struct {
B
foo
}
// Create an instance of the new type with its fields
// set from the source boo instance and marshal it.
return json.Marshal(T{B: B(b), foo: b.Foo})
}
https://play.golang.org/p/Go1w9quPkMa
Заметка об «анонимности»
Ярлык анонимный , как вы его используете и как он используется в цитируемой вами документации, устарел и неточен. Надлежащая метка для поля без явного имени встроена .
https://golang.org/ref/spec#Struct_types
Поле, объявленное с типом, но без явного имени поля, называется встроенным полем. Вложенное поле должно быть указано как имя типа T или как указатель на имя неинтерфейсного типа *T, и сам T не может быть типом указателя. Неполное имя типа действует как имя поля.
Различие важно, потому что в Go есть такая вещь, как «анонимные поля структуры», они используются довольно часто, но отличаются от встроенных полей. Например:
type T struct {
// F is an anonymous struct field, or
// a field of an anonymous struct type.
// F is not embedded however.
F struct {
foo string
bar int
}
}