如何将jsonb编码为golang中http响应的一部分

时间:2016-09-22 23:44:48

标签: json postgresql go

我很难将json移到电线上。

在Postgres数据库中有一个jsonb字段,我需要在它作为http响应通过网络发送之前添加到结构中。

如果struct的有效负载字段是string,则编组会像"{\"id\": \"3aa5fff0-ad91-41b1-84f0-d97f38e0e0f4\", \"user\": 1 }一样转义json。

如果struct的payload字段是json.RawMessage,则编组会将json转义为(我想象的)base64编码字节序列。

这是我正在编组并写入http响应流的结构:

type NestJobReturn struct { Status string `json:"status"` Nest json.RawMessage `json:"nest"` }

我构建了这个结构的ret实例并将其打印出来。如果我使用%v它显示字节,%s将其显示为正确的,未转义的json字符串:

log("Value of ret.Nest: %v", ret.Nest) // Value of ret.Nest: [123 34 105 ... log("Value of ret.Nest as a string: %s", ret.Nest) // Value of ret.Nest as a string: {"id": "f053...

马歇林和i / o就这样完成了:

js, _ := json.Marshal(ret) res.Header().Set("Content-Type", "application/json") res.Write(js)

客户端目前收到的整个邮件有点像这样:

{"status":"ok","nest":"eyJpZCI6ICJmMD..."}

...但“nest”的目标值是数据库中jsonb列的有效json。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您需要将嵌套字段定义为pointerjson.RawMessage,例如

type NestJobReturn struct {
    Status string           `json:"status"`
    Nest   *json.RawMessage `json:"nest"`
}

jsonStr := `{"type": "Object", "desc": "Simple nested object"}`
raw := json.RawMessage(jsonStr)

ret := NestJobReturn {
    Status: "DONE",
    Nest:   &raw,
}

一个工作示例https://play.golang.org/p/Ju7kgbawss

答案 1 :(得分:1)

您需要将指针编组到ret而不是ret本身

只需改变
js, _ := json.Marshal(&ret)
type RawMessage []byte // MarshalJSON returns m as the JSON encoding of m. func (m RawMessage) MarshalJSON() ([]byte, error) { return m, nil } // UnmarshalJSON sets *m to a copy of data. func (m *RawMessage) UnmarshalJSON(data []byte) error { if m == nil { return errors.New("json.RawMessage: UnmarshalJSON on nil pointer") } *m = append((*m)[0:0], data...) return nil }

它应该开始工作 playground link

更好的是,您可以通过使用I Putu Susila's answer或使用这个稍微调整过的版本替换json.RawMessage来使您的结构变得白痴

<iframe id="google_ads_iframe_/20346936/skysports/homepage_0" title="3rd party ad content" name="google_ads_iframe_/20346936/skysports/homepage_0" width="728" height="90" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" src="javascript:&quot;<html><body style='background:transparent'></body></html>&quot;" style="border: 0px; vertical-align: bottom; height: 90px;"></iframe>

然后你的结构将始终正确地制造自己 playground link

这是the github issue中针对这个怪癖提出的修正(链接由I Putu Susila's comment提供),但大家一致认为,即使这是RawMessage应该如何行事,他们也可以&#39;由于go标准库的兼容性保证,现在改变它。幸运的是,仅仅因为他们无法在标准库中修复它并不意味着您无法在自己的代码库中修复它。