在 go 中动态编码 json 键



我希望 json 输出如下所示。请注意,根据参数类型(如documenttext(,下一个键更改为documenttext

"components": [
{
"type" : "header",
"parameters": [
{
"type": "document",
"document": {
"filename":"dummy.pdf",
"link": "https://en.unesco.org/inclusivepolicylab/sites/default/files/dummy-pdf_2.pdf"
}
}
]
},
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "replacement_text"
}
] 
}
]

这是我的结构定义:

type Component struct {
Type       string      `json:"type,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
}
type Parameter struct {
Type            string `json:"type,omitempty"`
TypeInformation map[string]interface{}
}

当我编码它时,它是这样的:

"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"TypeInformation": {
"text": "Param1"
}
},
{
"type": "text",
"TypeInformation": {
"text": "param2"
}
}
]
},
{
"type": "header",
"parameters": [
{
"type": "document",
"TypeInformation": {
"document": {
"link": "http://link",
"filename": "dummy.pdf"
}
}
}
]
}
]

我不希望 json 中的TypeInformation键,我只想要内部对象。我该怎么做?

与其像使用Parameter那样使用具有任意映射的"泛型"结构,不如为每个参数类型使用不同的具体类型。然后,只需将它们放入一片空接口和 json 中即可。元帅会知道该怎么做。

type Object struct {
Components []Component `json:"components"`
}
type Component struct {
Type       string        `json:"type,omitempty"`
Parameters []interface{} `json:"parameters,omitempty"`
}
type TextParameter struct {
Type textType `json:"type"`
Text string   `json:"text"`
}
type DocumentParameter struct {
Type     documentType `json:"type"`
Document Document     `json:"document"`
}
type Document struct {
FileName string `json:"filename"`
Link     string `json:"link"`
}
// used to "hard code" the type of the parameter
type textType struct{}
func (textType) MarshalJSON() ([]byte, error) { return []byte(`"text"`), nil }
// used to "hard code" the type of the parameter
type documentType struct{}
func (documentType) MarshalJSON() ([]byte, error) { return []byte(`"document"`), nil }

然后,您可以像这样初始化实例:

obj := Object{
Components: []Component{{
Type: "header",
Parameters: []interface{}{
DocumentParameter{Document: Document{
FileName: "dummy.pdf",
Link:     "https://en.unesco.org/inclusivepolicylab/sites/default/files/dummy-pdf_2.pdf",
}},
},
}, {
Type: "body",
Parameters: []interface{}{
TextParameter{Text: "replacement_text"},
},
}},
}

https://play.golang.org/p/aNpnSGn980a

如果默认的 golang 行为不合适,您可以自定义结构的封送行为。这是通过在结构上实现封送器接口来实现的。

例:

func (p Parameter) MarshalJSON() ([]byte, error) {
r := fmt.Sprintf(`{"type":"%v",`, p.Type)
switch p.Type {
case "document":
f := `"document":`
b, _ := json.Marshal(p.TypeInformation[p.Type])
r = r + f + string(b) + "}"
case "text":
f := `"text":`
b, _ := json.Marshal(p.TypeInformation[p.Type])
r = r + f + string(b) + "}"
}
return json.Marshal(r)
}

这里的工作示例

最新更新