encoding/jsonMarshalerUnmarshaler
但有一个案例比较棘手:包含转义 JSON 元素的 JSON 文档。如下所示:
{
"id": 12345,
"name": "Test Document",
"payload": "{"message":"hello!"}"
}
我不建议构建像这样创建文档的应用程序,但有时候这样的情况是难以避免的,你希望像平常的 JSON 那样,一步就能解析这个文档。也许你从如下两种类型开始:
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 示例中生成初始结构体,不妨试一下!
LogEntry.PayloadstringLogPayloadencoding/jsonpayloadLogPayloadUnmarshalerLogPayload
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.UnmarshalLogPayload
type fauxLogPayload LogPayload
fauxLogPayloadLogPayload
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 找到这些代码。
encoding/decoding
Cheers!
main.go