如何像匿名结构一样编组结构?
How to marshal struct as if it were an anonymous struct?
documentation 状态:
Anonymous struct fields are usually marshaled as if their inner exported fields were fields in the outer struct.
例如:
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。
您必须为此实施自定义 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
关于“匿名”的注释
标签 anonymous 在您使用时以及在您引用的文档中使用时,已经过时且不精确。没有明确名称的字段的正确标签是 embedded.
https://golang.org/ref/spec#Struct_types
A field declared with a type but no explicit field name is called an
embedded field. An embedded field must be specified as a type name T
or as a pointer to a non-interface type name *T, and T itself may not
be a pointer type. The unqualified type name acts as the field name.
区别很重要,因为 Go 中有“匿名结构字段”这样的东西,它经常使用,但它不同于 embedded 字段。例如:
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
}
}
documentation 状态:
Anonymous struct fields are usually marshaled as if their inner exported fields were fields in the outer struct.
例如:
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。
您必须为此实施自定义 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
关于“匿名”的注释
标签 anonymous 在您使用时以及在您引用的文档中使用时,已经过时且不精确。没有明确名称的字段的正确标签是 embedded.
https://golang.org/ref/spec#Struct_types
A field declared with a type but no explicit field name is called an embedded field. An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.
区别很重要,因为 Go 中有“匿名结构字段”这样的东西,它经常使用,但它不同于 embedded 字段。例如:
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
}
}