为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
森林海 2021-11-22 18:18:14
我正在学习去和卡住的结构我需要生成json:{    "and" : [        { "term" : { "name.second" : "ba" } }      ]    }  }所以我可以用代码做到这一点:package mainimport (  "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 类型,它在代码中似乎没有必要,仅用于添加此行进行过滤。我可以避免使用它吗?我只想用类型过滤器来完成这个:type Filter struct {  And []struct{    Term map[string]interface{} `json:"term"`  } `json:"and"`}这看起来更具可读性并代表预期的结果,但我无法以这种方式创建 Term 的实例。有没有办法在不创建单独类型的情况下向 json 添加条款行?
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

您真正想要的是 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))

}


查看完整回答
反对 回复 2021-11-22
?
SMILET

TA贡献1796条经验 获得超4个赞

您可以围绕它创建一个包装函数。


package main


import (

    "fmt"

    "encoding/json"

)


type Filter struct {    

    And    []map[string]interface{}  `json:"and"`

}


func WrapFilter(i interface{}) Filter {

    return Filter{

        And: []map[string]interface{}{

            map[string]interface{}{

                "term": i,

            },

        },

    }

}


func main() {


    f := WrapFilter(map[string]string{"name.second": "ba"}) 

    json.Marshal(f) 


}

这样,您将始终"term"在编组的 JSON 中拥有二级密钥。


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 129 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信