type Struct struct {
   Value  string `json:"value"`
   Value1 string `json:"value_one"`
   Nest   Nested `json:"nest"`
}

type Nested struct {
   Something string `json:"something"`
}

我想添加不在 struct 定义中的元素,而不创建另一个 struct 类型.例如

Struct.Extra1 = Nested{"yy"}
Struct.Nested.Extra2 = "zz"

结果会怎样

{
    "Value": "xx",
    "Value1": "xx",
    "Extra1": {
      "Something", "yy"
    },
    "Nest": {
      "Something": "xx",
      "Extra2": "zz"
    }
}

SOLUTION1: 我想添加omitempty来实现这一点,但是这会使 struct 变得复杂.

type Struct struct {
   Value  string
   Value1 string
   Nest   Nested
   Extra1 Nested `json:"omitempty"`
}

type Nested struct {
   Something string
   Extra2 string `json:"omitempty"`
}

SOLUTION2:

myextras := make(map[string]interface{})
// get Struct.Nested in map[string]interface{} format
myextras = Struct.Nest
myextras["Extra2"] = "zz"

// get Struct in map[string]interface{} format
struct["Nest"] = myextras
struct["Extra1"] = Nested{"yy"}

// solves the problem with lots of type casting but doesn't support json tag naming

有没有更好的解决方案来添加嵌套元素,这些元素不是用支持json-tag的struct数据类型表示的,可以用来输出到用户.

推荐答案

基于这个答案:Can I use MarshalJSON to add arbitrary fields to a json encoding in golang?

您可以执行如下操作(演示:http://play.golang.org/p/dDiTwxhoNn):

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type Book struct {
    Title  string
    Author string

    // extra is used for additional dynamic element marshalling
    extra func() interface{}
}

type FakeBook Book

func (b *Book) SetExtra(fn func() interface{}) {
    b.extra = fn
}

func (b *Book) MarshalJSON() ([]byte, error) {
    if b.extra == nil {
        b.extra = func() interface{} { return *b }
    }

    return json.Marshal(b.extra())
}

func main() {
    ms := &Book{
        Title:  "Catch-22",
        Author: "Joseph Heller",
    }

    ms.SetExtra(func() interface{} {
        return struct {
            FakeBook
            Extra1 struct {
                Something string `json:"something"`
            } `json:"extra1"`
        }{
            FakeBook: FakeBook(*ms),
            Extra1: struct {
                Something string `json:"something"`
            }{
                Something: "yy",
            },
        }
    })

    out, err := json.MarshalIndent(ms, "", "  ")
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(string(out))

    mb := &Book{
        Title:  "Vim-go",
        Author: "Fatih Arslan",
    }

    mb.SetExtra(func() interface{} {
        return struct {
            FakeBook
            Something string `json:"something"`
        }{
            FakeBook:  FakeBook(*mb),
            Something: "xx",
        }
    })

    out, err = json.MarshalIndent(mb, "", "  ")
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(string(out))

    mc := &Book{
        Title:  "Another-Title",
        Author: "Fatih Arslan",
    }

    out, err = json.MarshalIndent(mc, "", "  ")
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(string(out))
}

Go相关问答推荐

gorm如何声明未自动更新的unix时间戳米尔斯字段

正在使用terratest执行terraform脚本测试,但遇到错误退出状态1

使用Digitorus/pdfsign在GO(Golang)中签署pdf文件

Websocket服务器实现与x/net库trowing 403

Golang String

无法获取RPC描述符

";无效的复制因子;融合Kafka Go客户端

Go:如何在不加载正文的情况下创建 http 代理通行证

无法将 graphql-ws 连接到 gqlgen

拆分文本并按空格获取字符串数组,如果文本长度超过 500,则获取字符串数组

如何使用 fyne Go 使用 canvas.NewText() 使文本可滚动

Go 中的 HTTP 请求验证中间件

使用 go.work 文件在多个测试文件上运行 go test 命令

在删除级联时无法在 Gorm 中按预期工作

如何在gin中获取参数值数组

如何在 GORM 中迭代一个 int 数组

使用 bolthold 3 条件进行 boltDB 查询

如何在眼镜蛇(golang)中将标志作为参数传递?

如何使路径/不匹配 Golang net/http 中所有其他不匹配的路径

Golang 泛型同时具有接口和实现