Golang 通用 JSON 编组
Golang generic JSON marshalling
我正在从事基于 JSON 通信的小型服务器-客户端项目。但是我 运行 遇到了问题。我正在尝试创建一个具有通用消息正文的响应结构。这意味着我有一个映射,其中一个键作为字符串,一个 json 原始消息作为值。最后,消息正文应该适用于任何类型(字符串、整数、数组)
package main
import (
"encoding/json"
"fmt"
)
type ServerResponse struct {
Code int `json:"code" bson:"code"`
Type string `json:"type" bson:"type"`
Body map[string]json.RawMessage `json:"body" bson:"body"`
}
func NewServerResponse() *ServerResponse {
return &ServerResponse{Body: make(map[string]json.RawMessage)}
}
func main(){
serverResponse := NewServerResponse()
serverResponse.Code = 100
serverResponse.Type = "molly"
serverResponse.Body["string"] = json.RawMessage("getIt")
serverResponse.Body["integer"] = json.RawMessage{200}
serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)
if d, err := json.Marshal(&serverResponse); err != nil{
fmt.Println("Error " + err.Error())
}else{
fmt.Println(string(d))
}
}
但是输出如下。
{
"code":100,
"type":"molly",
"body": {
"array":"WyJhIiwgImIiLCAiYyJd",
"integer":"yA==",
"string":"Z2V0SXQ="
}
}
这些值似乎是 Base64 编码的并且在双引号内。 Tihs 应该是预期的输出
{
"code":100,
"type":"molly",
"body": {
"array":["a", "b", "c"],
"integer":200,
"string":"getIt"
}
}
这可能吗?或者我是否必须为每个响应编写特定的结构类型?
原始消息必须有效JSON。
为字符串添加引号使其成为有效的 JSON 字符串。
serverResponse.Body["string"] = json.RawMessage("\"getIt\"")
JSON 数字是十进制字节序列。数字不是问题中尝试的单个字节的值。
serverResponse.Body["integer"] = json.RawMessage("200")
这个如你所愿。
serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)
问题程序编译运行出错。检查这些错误并修复它们会得出我上面的建议。
另一种方法是将 json.RawMessage
的使用替换为 interface{}
:
type ServerResponse struct {
Code int `json:"code" bson:"code"`
Type string `json:"type" bson:"type"`
Body map[string]interface{} `json:"body" bson:"body"`
}
像这样设置响应正文:
serverResponse.Body["string"] = "getIt"
serverResponse.Body["integer"] = 200
serverResponse.Body["array"] = []string{"a", "b", "c"}
您可以使用 json.RawMessage 值:
serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)
我正在从事基于 JSON 通信的小型服务器-客户端项目。但是我 运行 遇到了问题。我正在尝试创建一个具有通用消息正文的响应结构。这意味着我有一个映射,其中一个键作为字符串,一个 json 原始消息作为值。最后,消息正文应该适用于任何类型(字符串、整数、数组)
package main
import (
"encoding/json"
"fmt"
)
type ServerResponse struct {
Code int `json:"code" bson:"code"`
Type string `json:"type" bson:"type"`
Body map[string]json.RawMessage `json:"body" bson:"body"`
}
func NewServerResponse() *ServerResponse {
return &ServerResponse{Body: make(map[string]json.RawMessage)}
}
func main(){
serverResponse := NewServerResponse()
serverResponse.Code = 100
serverResponse.Type = "molly"
serverResponse.Body["string"] = json.RawMessage("getIt")
serverResponse.Body["integer"] = json.RawMessage{200}
serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)
if d, err := json.Marshal(&serverResponse); err != nil{
fmt.Println("Error " + err.Error())
}else{
fmt.Println(string(d))
}
}
但是输出如下。
{
"code":100,
"type":"molly",
"body": {
"array":"WyJhIiwgImIiLCAiYyJd",
"integer":"yA==",
"string":"Z2V0SXQ="
}
}
这些值似乎是 Base64 编码的并且在双引号内。 Tihs 应该是预期的输出
{
"code":100,
"type":"molly",
"body": {
"array":["a", "b", "c"],
"integer":200,
"string":"getIt"
}
}
这可能吗?或者我是否必须为每个响应编写特定的结构类型?
原始消息必须有效JSON。
为字符串添加引号使其成为有效的 JSON 字符串。
serverResponse.Body["string"] = json.RawMessage("\"getIt\"")
JSON 数字是十进制字节序列。数字不是问题中尝试的单个字节的值。
serverResponse.Body["integer"] = json.RawMessage("200")
这个如你所愿。
serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)
问题程序编译运行出错。检查这些错误并修复它们会得出我上面的建议。
另一种方法是将 json.RawMessage
的使用替换为 interface{}
:
type ServerResponse struct {
Code int `json:"code" bson:"code"`
Type string `json:"type" bson:"type"`
Body map[string]interface{} `json:"body" bson:"body"`
}
像这样设置响应正文:
serverResponse.Body["string"] = "getIt"
serverResponse.Body["integer"] = 200
serverResponse.Body["array"] = []string{"a", "b", "c"}
您可以使用 json.RawMessage 值:
serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)