将`interface{}`类型的数据编组为JSON格式。

huangapple go评论89阅读模式
英文:

Marshal interface{} into json

问题

我想生成一个类似以下结构的 JSON:

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

但我希望我的代码足够通用,以便我可以用任何其他类型的 JSON 对象替换键值对 "C"。我尝试了下面的方法:

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"
}

有没有其他方法可以解决这个问题?

英文:

I want to generate a json that's something like this:

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

But I want to keep my code generic enough that I can replace the key-pair "C" with any other type of json object that I want. I tried doing something like what I have below:

    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)
    }

But the output is just this:

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

Is there a different way to approach this?

答案1

得分: 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

当然,在你的情况下,你可以在需要之前将值进行编组,以获取原始字节。

英文:

This is precisely why json.RawMessage exists.

Here is an example straight from the Go docs:

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)

}

Here is the output:

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

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

Of course you can marshal a value before time to get the raw bytes in your case.

答案2

得分: -1

package main

import (
	"encoding/json"
	"fmt"
)

type JsonMessage struct {
	A          int    `json:"A"`
	B          string `json:"B,omitempty"`
	// 只需将此字段大写,它将包含在 JSON 字符串中
	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"}}
英文:
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"}}

huangapple
  • 本文由 发表于 2017年6月21日 08:35:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/44665057.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定