将interface{}转换为json格式

13

我想生成一个类似于这样的json:

{
   "A": 1,
   "B": "bVal",
   "C": "cVal"
}

但我希望我的代码足够通用,以便我可以替换“C”键值对为我想要的任何其他类型的 JSON 对象。我尝试了下面的操作:

    type JsonMessage struct {
        A int `json:"A"`
        B string `json:"B,omitempty"`
        genericObj interface{} 
    }

    type JsonObj struct {
        C string `json:"C"`
    }

    func main() {
        myJsonObj := JsonObj{C: "cVal"}
        myJson := JsonMessage{A: 1, B: "bValue", genericObj: myJsonObj}

        body, _ := json.Marshal(myJson)
        fmt.Print(body)
    }

但输出只是这个:

{
   "A": 1,
   "B": "bVal"
}

还有其他方法来处理这个问题吗?


当我在这里尝试了你的代码 https://play.golang.org/p/1NDMsUJtqW 时,它可以正常工作。{"A":1,"B":"bValue","GenericObj":{"C":"cVal"}} - rnk
糟糕 - “GenericObj” 应该是一个私有变量 "genericObj"。而且在你的 playground 输出中,它将 "GenericObj" json 键包裹在 "C":"cVal" 的周围,这不是我想要的。 - J.Doe
4
就此而言,在Go中未导出的字段不会被编组。 - squiguy
2个回答

15

这正是为什么json.RawMessage存在的原因。

下面是来自Go文档的一个示例:

package main

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

func main() {
    h := json.RawMessage(`{"precomputed": true}`)

    c := struct {
        Header *json.RawMessage `json:"header"`
        Body   string           `json:"body"`
    }{Header: &h, Body: "Hello Gophers!"}

    b, err := json.MarshalIndent(&c, "", "\t")
    if err != nil {
        fmt.Println("error:", err)
    }
    os.Stdout.Write(b)

}

这里是输出结果:

{
    "header": {
        "precomputed": true
    },
    "body": "Hello Gophers!"
}

Go Playground: https://play.golang.org/p/skYJT1WyM1C

当然,在适当的时候您可以将值进行编组,以获取您的情况下的原始字节。


在给定的示例中,输出的 JSON 是否总是包含一个名为“Header”的对象,其中包含 RawMessage?是否有一种方法可以根据我们的构造方式动态地将 JSON 字段名称从“Header”更改为其他名称? - J.Doe
1
基本上在我的代码中,我将获得一个从输入json反序列化的map[string]interface,并且我想直接将其放入我的输出JsonMessage结构中,而不添加任何顶级json字段。目前提出的方法将使用JsonMessage字段的名称(即“Header”)将输入json包装在另一个json字段中。 - J.Doe
1
@J.Doe 我不相信有一种动态更改JSON字段名称的方法。除非进行一些代码生成,否则似乎不可能。 - squiguy
就像我想的一样。谢谢@ - J.Doe
如果有一个有限的JSON字段名称集合,您可以定义所有这些字段并检查哪个被设置。 - Pita

-1
package main

import (
    "encoding/json"
    "fmt"
)

type JsonMessage struct {
    A          int    `json:"A"`
    B          string `json:"B,omitempty"`
    // simply make this field capitalized,and it will be included in the 
    // json string
    GenericObj interface{}
}

type JsonObj struct {
    C string `json:"C"`
}

func main() {
    myJsonObj := JsonObj{C: "cVal"}
    myJson := JsonMessage{A: 1, B: "bValue", GenericObj: myJsonObj}

    body, _ := json.Marshal(myJson)
    fmt.Println(string(body))
}

{"A":1,"B":"bValue","GenericObj":{"C":"cVal"}}

输出结果显然与OP所期望的输出不同,因此这并不能回答问题。 - jso
无法解决问题,因为它需要私有变量genericObj。 - dchang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接