Golang通用的JSON编组

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

Golang generic JSON marshalling

问题

我正在进行一个基于JSON通信的小型服务器-客户端项目。但是我遇到了问题。我试图创建一个带有通用消息体的响应结构体。这意味着我有一个以字符串为键、以JSON原始消息为值的映射。最终,消息体应该适用于任何类型(字符串、整数、数组)。

但是输出结果如下所示:

{
"code":100,
"type":"molly",
"body": {
"array":"WyJhIiwgImIiLCAiYyJd",
"integer":"yA==",
"string":"Z2V0SXQ="
}
}

看起来值被Base64编码并放在双引号内。应该得到以下预期输出:

{
"code":100,
"type":"molly",
"body": {
"array":["a", "b", "c"],
"integer":200,
"string":"getIt"
}
}

这种情况是否可能?还是我必须为每个响应编写一个特定的结构体类型?

英文:

I'm working on s small server-client project based on JSON communication. But i run into issues. I'm trying to create a response struct with a generic message body. This means I have an map with a key as string and a json raw message as value. In the end the message body should work for any type (strings, integers, arrays)

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

But the output is as follow.

{
  "code":100,
  "type":"molly",
  "body":  {
            "array":"WyJhIiwgImIiLCAiYyJd",
            "integer":"yA==",
            "string":"Z2V0SXQ="
           }
}

It seems like the values are Base64 encoded and inside double quotes. Tihs should be the expected output

{
  "code":100,
  "type":"molly",
  "body":  {
            "array":["a", "b", "c"],
            "integer":200,
            "string":"getIt"
           }
}

Is this even possible? Or do I have to write a specific struct type for every response?

答案1

得分: 0

原始消息必须是有效的 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"]`)

Playground 示例

英文:

The raw message must be valid JSON.

Add quotes to the string to make it a valid JSON string.

serverResponse.Body["string"] = json.RawMessage("\"getIt\"")

JSON numbers are a sequence of decimal bytes. A number is not the value of a single byte as attempted in the question.

serverResponse.Body["integer"] = json.RawMessage("200")

This one works as you expected.

serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)

The program in the question compiles and runs with errors. Examining those errors and fixing them leads to my suggestions above.

An alternative approach is to replace the use of json.RawMessage with interface{}:

type ServerResponse struct {
  Code int                    `json:"code" bson:"code"`
  Type string                 `json:"type" bson:"type"`
  Body map[string]interface{} `json:"body" bson:"body"`
}

Set the response body like this:

serverResponse.Body["string"] = "getIt"
serverResponse.Body["integer"] = 200
serverResponse.Body["array"] = []string{"a", "b", "c"}

You can use json.RawMessage values:

serverResponse.Body["array"] = json.RawMessage(`["a", "b", "c"]`)

Playground example

huangapple
  • 本文由 发表于 2017年3月27日 17:17:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/43042422.html
匿名

发表评论

匿名网友

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

确定