今天我想和你们分享 Go 语言一些很是实用的技巧,用于编码和解码 JSON 文档。Go 语言的 encoding/json 包有一些有趣的特性,帮助咱们轻松地解析 JSON 文档。你能够轻松地将大多数实际应用中的 JSON 转换为带有 Go 语言结构体标签的接口或者是 Marshaler 和 Unmarshaler 接口。golang
但有一个案例比较棘手:包含转义 JSON 元素的 JSON 文档。以下所示:json
{ "id": 12345, "name": "Test Document", "payload": "{\"message\":\"hello!\"}" }
我不建议构建像这样建立文档的应用程序,但有时候这样的状况是难以免的,你但愿像日常的 JSON 那样,一步就能解析这个文档。也许你从以下两种类型开始:ide
type LogEntry struct { ID int `json:"id"` Name string `json:"name"` Payload string `json:"payload"` } type LogPayload struct { Message string `json:"message"` }
Matt Holt 的 json-to-go 可以帮助你从 JSON 示例中生成初始结构体,不妨试一下!ui
首先要将 LogEntry.Payload 的类型从 string 类型改成 LogPayload 类型。这点很重要,由于这是你最终想要获得的,这就是 encoding/json 包处理该元素的方式。如今的问题是 payload 元素的实际入站类型是一个 JSON 字符串。你须要在 LogPayload 类型上实现 Unmarshaler 接口,并将其解码为字符串,而后再解码为 LogPayload 类型。编码
func (lp *LogPayload) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { return err } if err := json.Unmarshal([]byte(s), lp); err != nil { return err } return nil }
看起来很棒,然而不幸的是第二个 json.Unmarshal 调用将会致使调用堆栈的递归。你须要将它解码成一个中间类型,你能够经过定义一个带有 LogPayload 基础类型的新类型来实现,例如这样:code
type fauxLogPayload LogPayload
你能够将上面的代码调整一下,将其解码为 fauxLogPayload 类型,而后将结果转换为 LogPayload 类型。递归
func (lp *LogPayload) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { return err } var f fauxLogPayload if err := json.Unmarshal([]byte(s), &f); err != nil { return err } *lp = LogPayload(f) return nil }
如今,要解析整个文档的调用站点变得更好了,也简洁了:接口
func main() { doc := []byte(`{ "id": 12345, "name": "Test Document", "payload": "{\"message\":\"test\"}" }`) var entry LogEntry if err := json.Unmarshal(doc, &entry); err != nil { fmt.Println("Error!", err) } fmt.Printf("%v", entry) }
你能够在 Go Playground 找到这些代码。文档
我但愿这个例子说明了 Go 语言能够多么容易地将对 encoding/decoding 的关注点从业务逻辑中分离出来。你能够在任什么时候候使用此方法将基本 JSON 类型转换为更复杂的用户定义类型。字符串
Cheers!
感谢 Redditors BubuX 和 quiI ,他们建议连接到 JSON -to- Go ,并在 main.go 中为个人 JSON 使用 Go 语言的字符串文字。
原文连接: https://medium.com/@turgon/json-in-go-is-magical-c5b71505a937
译文连接:https://studygolang.com/articles/12619做者:turgon 译者:SergeyChang 校对:rxcai