【问题标题】:Golang generic JSON marshallingGolang 通用 JSON 编组
【发布时间】:2017-03-27 09:17:47
【问题描述】:

我正在开发一个基于 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.RawMessage 正是你想做的,但你真的应该把你的代码弄直:例如getItnot 有效的 JSON,因为它缺少双引号。试试 json.RawMessage("getIt")。你认为json.RawMessage{200} 会产生什么?请阅读 json.RawMessage 到底是什么,然后想想json.RawMessage{200} 产生了什么。您的代码无法编译,如果可以,它不会产生您显示的输出。请解决您的问题。
  • 嗯.. 这似乎有点奇怪。在 JetBrains Gogland IDE 中,代码编译并运行,没有任何错误。而同样的代码在 Go Playground 中失败了。那么我可以只对对象使用原始消息吗?不是单个键/值对?
  • 当然你可以将它用于单个值:json.RawMessage([]byte("200"))json.RawMessage([]byte("true"))。很简单。

标签: arrays json go marshalling


【解决方案1】:

原始消息必须是有效的 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 example

【讨论】:

    猜你喜欢
    • 2015-10-25
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    相关资源
    最近更新 更多