在[] struct中附加的不需要的类型

时间:2015-11-19 13:33:14

标签: go

我正在学习去克服结构

我需要生成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中吗?

2 个答案:

答案 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}}具有第二级密钥。