英文:
Can I skip a json tag while Marshalling a struct in Golang?
问题
我有一个场景,我想在Golang中编组结构体时跳过一个JSON标签。这可能吗?如果可以,我该如何实现?
例如,我得到了这个JSON:
{"Employee":{"Interface":{"Name":"xyz", "Address":"abc"}}}
但我希望JSON是这样的:
{"Employee":{"Name":"xyz", "Address":"abc"}}
英文:
I have a scenario where I would like to skip a json tag while marshalling a struct in Golang. Is that possible? If so how can I achieve this?
For example I am getting this json:
{"Employee":{"Interface":{"Name":"xyz", "Address":"abc"}}}
But I want the json to be:
{"Employee":{"Name":"xyz", "Address":"abc"}}
答案1
得分: 1
你可以使用匿名结构体
type Employee struct {
Interface struct {
Name string
Address string
}
}
func main() {
a := Employee{
Interface: struct {
Name string
Address string
}{
Name: "xyz",
Address: "abc",
},
}
b := struct {
Employee struct {
Name string
Address string
}
}{
Employee: a.Interface,
}
jsonResult, _ := json.Marshal(b)
fmt.Println(string(jsonResult)) // {"Employee":{"Name":"xyz","Address":"abc"}}
}
英文:
You can use anonymous structures
type Employee struct {
Interface Interface
}
type Interface struct {
Name string
Address string
}
func main() {
a := Employee{Interface: Interface{Name: "xyz", Address: "abc"}}
b := struct {
Employee Interface
}{
Employee: a.Interface,
}
jsonResult, _ := json.Marshal(b)
fmt.Println(string(jsonResult)) // {"Employee":{"Name":"xyz","Address":"abc"}}
}
答案2
得分: 1
如果Interface
字段的类型不是一个实际的接口类型,而是一个结构体类型,那么你可以嵌入该字段,这将使嵌入的结构体字段成为Employee
的一部分,并将其编组为JSON以获得所需的输出。
type Employee struct {
Interface // 嵌入字段
}
type Interface struct {
Name string
Address string
}
func main() {
type Output struct{ Employee Employee }
e := Employee{Interface: Interface{Name: "xyz", Address: "abc"}}
out, err := json.Marshal(Output{e})
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
如果Interface
字段的类型是一个实际的接口类型,那么嵌入将无法帮助,相反,你可以让Employee
类型实现json.Marshaler
接口,并自定义生成的JSON。
例如,你可以这样做:
type Employee struct {
Interface Interface `json:"-"`
}
func (e Employee) MarshalJSON() ([]byte, error) {
type E Employee
obj1, err := json.Marshal(E(e))
if err != nil {
return nil, err
}
obj2, err := json.Marshal(e.Interface)
if err != nil {
return nil, err
}
// 通过从obj1中删除'}'和从obj2中删除'{',然后将obj2附加到obj1来连接两个对象
//
// 注意:如果Interface字段为nil,或者它包含的类型不是结构体、映射或指向这些类型的指针,则会生成无效的JSON,并且编组将失败并报错。
// 如果你的程序中可能出现这些情况,你应该在这里添加一些逻辑来处理它们。
return append(obj1[:len(obj1)-1], obj2[1:]...), nil
}
英文:
If the Interface
field's type is not an actual interface but a struct type then you could embed that field, this will promote the embedded struct's fields to Employee
and marshaling that into JSON will get you the output you want.
type Employee struct {
Interface // embedded field
}
type Interface struct {
Name string
Address string
}
func main() {
type Output struct{ Employee Employee }
e := Employee{Interface: Interface{Name: "xyz", Address: "abc"}}
out, err := json.Marshal(Output{e})
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
https://play.golang.org/p/s5SFfDzVwPN
If the Interface
field's type is an actual interface type then embedding won't help, instead you could have the Employee
type implement the json.Marshaler
interface and customize the resulting JSON.
For example you could do the following:
type Employee struct {
Interface Interface `json:"-"`
}
func (e Employee) MarshalJSON() ([]byte, error) {
type E Employee
obj1, err := json.Marshal(E(e))
if err != nil {
return nil, err
}
obj2, err := json.Marshal(e.Interface)
if err != nil {
return nil, err
}
// join the two objects by dropping '}' from obj1 and
// dropping '{' from obj2 and then appending obj2 to obj1
//
// NOTE: if the Interface field was nil, or it contained a type
// other than a struct or a map or a pointer to those, then this
// will produce invalid JSON and marshal will fail with an error.
// If you expect those cases to occur in your program you should
// add some logic here to handle them.
return append(obj1[:len(obj1)-1], obj2[1:]...), nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论