我正在学习去克服结构
我需要生成json:
{
"and" : [
{ "term" : { "name.second" : "ba" } }
]
}
}
所以我可以用代码来做到这一点:
package main
import (
"encoding/json"
"fmt"
)
type Term map[string]interface{}
type TermHash struct {
Term `json:"term"`
}
type Filter struct {
And []TermHash `json:"and"`
}
func main() {
var filter Filter
filter.And = append(filter.And, TermHash{ Term{"name.second" : "ba"}})
jsonFilter, _ := json.MarshalIndent(filter, "", " ")
fmt.Printf(string(jsonFilter))
}
但我真的不想使用单独的TermHash和Term类型,它在代码中似乎是不必要的,只用于添加这些行来过滤。我可以避免使用它吗?
我只想用只有类型Filter:
来实现这一点type Filter struct {
And []struct{
Term map[string]interface{} `json:"term"`
} `json:"and"`
}
这看起来更具可读性并代表预期结果,但我不能以这种方式创建Term的实例。有一种方法可以在不创建单独类型的情况下将条款行添加到json中吗?
答案 0 :(得分:3)
您真正想要的是JSON编码Term
的自定义方式。它不是一个简单的地图,而是整理好像是一个包含地图的对象。所以,让我们为它编写自定义MarshalJSON
:
type Term map[string]interface{}
func (t Term) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
T map[string]interface{} `json:"term"`
}{t})
}
我们在这里创建一个匿名struct
,用自己填充,然后将其编组为JSON。请注意这里使用map[string]interface{}
。虽然看起来像Term
,但它实际上是一种不同的类型,它有自己的JSON编码方式。如果您尝试在此处保存一些输入并使用T Term
,您会发现自己处于无限循环中。 (这种创建与其他类型具有相同结构的新类型的想法是Go的主要部分。)
现在我们的数据结构很简单;只是一段术语:
type Filter struct {
And []Term `json:"and"`
}
func main() {
var filter Filter
filter.And = append(filter.And, Term{"name.second" : "ba"})
jsonFilter, _ := json.MarshalIndent(filter, "", " ")
fmt.Printf(string(jsonFilter))
}
也就是说,您也可以采用其他方式使您的数据模型更接近JSON。在这种情况下,Term
应该是结构,而不是地图。你可能会这样写:
type Term struct {
Values map[string]interface{} `json:"term"`
}
func NewTerm(key, value string) Term {
return Term{map[string]interface{}{key: value}}
}
type Filter struct {
And []Term `json:"and"`
}
func main() {
var filter Filter
filter.And = append(filter.And, NewTerm("name.second", "ba"))
jsonFilter, _ := json.MarshalIndent(filter, "", " ")
fmt.Printf(string(jsonFilter))
}
答案 1 :(得分:1)
你可以围绕它创建一个包装函数。
"term"
这样,您的封送JSON中始终有{{1}}具有第二级密钥。