我可以使用MarshalJSON向golang中的json编码添加任意字段吗?

我可以使用MarshalJSON向golang中的json编码添加任意字段吗?,json,go,Json,Go,假设我已经编写了以下代码段。操场上为有兴趣的人提供完整的代码 type Book struct { Title string Author string } func main() { ms := Book{"Catch-22", "Joseph Heller"} out, err := json.MarshalIndent(ms, "", " ") if err != nil { log.Fatalln(err) } fmt.P

假设我已经编写了以下代码段。操场上为有兴趣的人提供完整的代码

type Book struct {
  Title        string
  Author       string
}

func main() {
  ms := Book{"Catch-22", "Joseph Heller"}
  out, err := json.MarshalIndent(ms, "", "  ")
  if err != nil {
    log.Fatalln(err)
  }
  fmt.Println(string(out))
}
这段代码输出以下内容,与我预期的完全一致:

{
  "Title": "Catch-22",
  "Author": "Joseph Heller"
}
假设我想在JSON输出中添加一个字段,而不将其包含在
结构中。也许是一种类型:

{
  "Title": "Catch-22",
  "Author": "Joseph Heller",
  "Genre": "Satire"
}
我可以使用
MarshalJSON()
Marshal()
上向JSON负载添加任意字段吗?比如:

func (b *Book) MarshalJSON() ([]byte, error) {
    // some code
}

其他人让我认为这应该是可能的,但我正在努力找出实现

这个问题的一个可能答案是struct literal(),尽管我希望它更一般一些,不需要重新映射所有的struct字段:

func (b *Book) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct{
        Title    string
        Author   string
        Genre    string
    } {
        Title: b.Title,
        Author: b.Author,
        Genre: "Satire",
    })
}

这里有一个比我上一个更好的答案

type FakeBook Book

func (b Book) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        FakeBook
        Genre string
    }{
        FakeBook: FakeBook(b),
        Genre:    "Satire",
    })
}
由于匿名结构字段是“合并”的(还有一些额外的注意事项),我们可以使用它来避免重新映射单个字段。请注意,使用了
FakeBook
类型以避免出现无限递归


操场:

整理
地图是解决问题的另一种方法

tmap:=make(映射[字符串]接口{})
tmap[“struct”]=struct{
StructValue字符串`json:“struct_value”`
}{
“价值02”,
}
tmap[“字符串”]=“值01”
out,err:=json.marshallindent(tmap,“,”)
如果出错!=零{
log.Fatalln(错误)
}
fmt.Println(字符串(输出))
这将输出:

{
“字符串”:“值01”,
“结构”:{
“结构值”:“值02”
}
}
如果您有许多任意键名,这可能是一个很好的解决方案


操场:

这是一种处理方法:

类型对象结构{
一串
B int
额外映射[字符串]接口{}`json:“-”`
}
func(o对象)MarshalJSON()([]字节,错误){
类型Object_uuObject
b、 err:=json.Marshal(对象_uo))
如果错误!=零{
返回零,错误
}
如果o.Extra==nil | | len(o.Extra)==0{
返回b,无
}
m、 err:=json.Marshal(o.Extra)
如果错误!=零{
返回零,错误
}
如果len(b)==2{
返回m,零
}否则{
b[len(b)-1]=','
返回append(b,m[1:]…),nil
}
}
您可以将任何附加字段添加到
Extra
映射中,这些字段将显示在输出中而不嵌套