我最近遇到了以下问题,但没有找到任何解决方案。我在 Go 中有两种结构类型,我们称它们为父级和子级。 子级有一个匿名字段,类型为 *Parent。但是,Parent 有一个名为"ID"的字段,它具有第三个结构的类型,我们将该类型称为"IDType"(在我的实际问题中,这是一种方言/sql。空英特64(。IDType 有一个 int 字段和一个布尔字段。
问题如下:父级和子级都实现了 MarshalJSON((,因为对于父级,我只希望 JSON 中的 int 字段和子级相同。但是,似乎两个 MarshalJSON 都推断出只有父级的值被编码在最终的 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}
由于自定义 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 将为您提供所需的 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}
另一个笨拙的选择是分别封送父子,然后通过剪切最后一个/第一个字符手动加入,与,
连接并换入{}
。