我最近遇到了以下问题,但没有找到任何解决方案。我在Go中有两个结构类型,让我们称它们为Parent和Child。 Child有一个* Parent类型的匿名字段。但是,Parent有一个名为“ID”的字段,它具有第三个结构的类型,我们将其称为“IDType”(在我的实际问题中,这是一个方言/ sql.NullInt64)。 IDType有一个int字段和一个bool字段。
问题如下:Parent和Child都实现了MarshalJSON(),因为对于Parent我只希望JSON内部的int字段和Child相同。但是,似乎两个MarshalJSON都推断出结果只有Parent的值在最终的JSON中编码。
也许一个最小的例子让它更容易理解:
package main
import (
"encoding/json"
"fmt"
"os"
)
type IDType struct {
Value int
Valid bool
}
type Parent struct {
ID IDType `json:"id"`
SomeString string `json:"some_string"`
}
type Child struct {
*Parent
Status int `json:"status"`
}
func (parent *Parent) MarshalJSON() ([]byte, error) {
type Alias Parent
fmt.Println("Parent")
return json.Marshal(struct {
*Alias
ID int `json:"id"`
}{
Alias: (*Alias)(parent),
ID: parent.ID.Value,
})
}
func (child *Child) MarshalJSON() ([]byte, error) {
type Alias Child
fmt.Println("Child")
return json.Marshal(struct {
*Alias
Status int `json:"status"`
}{
Alias: (*Alias)(child),
Status: child.Status,
})
}
func main() {
ID := IDType{Value: 1, Valid: true}
parent := Parent{ID: ID, SomeString: "Hello"}
child := Child{Parent: &Parent{ID: ID, SomeString: "Hello"}, Status: 1}
json.NewEncoder(os.Stdout).Encode(&parent)
json.NewEncoder(os.Stdout).Encode(&child)
}
输出结果为:
Parent
{"some_string":"Hello","id":1}
Child
Parent
{"some_string":"Hello","id":1}
我期待的是:
Parent
{"some_string":"Hello","id":1}
Child
Parent
{"some_string":"Hello","id":1, "status": 1}
答案 0 :(得分:2)
由于自定义ID编组,您看起来只定义了自定义封送逻辑。仅定义未嵌入的IDType
类型的自定义编组,因此不会对其他类型的编组造成任何问题:
func (id *IDType) MarshalJSON() ([]byte, error) {
return json.Marshal(id.Value)
}
并且不需要其他自定义编组。有了这个,输出将是:
{"id":1,"some_string":"Hello"}
{"id":1,"some_string":"Hello","status":1}
在Go Playground上尝试。
答案 1 :(得分:1)
您应该具有指向父级的父级或嵌入值的命名指针。
选项1将为您提供您期望的JSON。
type Child struct {
Parent
Status int `json:"status"`
}
>> {"some_string":"Hello","id":1, "status": 1}
选项2将父项作为子节点。
type Child struct {
Parent *Parent
Status int `json:"status"`
}
>> {Parent: {"some_string":"Hello","id":1}, "status": 1}
另一个愚蠢的选择是组织父母&单独的子项,然后通过剪切最后/第一个字符手动加入,加入,
并换入{}
。