解组嵌套 json 字符串使用 json.RawMessage
Unmarshaling nested json string use json.RawMessage
我无法思考如何解组来自先前解组的 json 字节数组的原始 json 字符串。我有当前代码:
type Message struct {
Event string
Data json.RawMessage // how data is parsed depends on the event
}
type CreateMessage struct {
id int
}
var evt = []byte(`{"event": "create", "data" :{"id":5 }}`)
func main() {
var message Message
log.Println(string(evt))
json.Unmarshal(evt, &message)
log.Println(message)
log.Println(message.Event)
log.Println(string(message.Data))
fmt.Printf("%+v\n", message)
var message2 = new(CreateMessage)
err := json.Unmarshal( message.Data, &message2 )
log.Println(message2)
log.Println(err)
}
输出为:
2015/06/29 23:22:10 {"event": "create", "data" :{"id":5 }}
2015/06/29 23:22:10 {create [123 34 105 100 34 58 53 32 125]}
2015/06/29 23:22:10 create
2015/06/29 23:22:10 {"id":5 }
{Event:create Data:[123 34 105 100 34 58 53 32 125]}
2015/06/29 23:22:10 &{0}
2015/06/29 23:22:10 <nil>
为什么我不能将数据解组为 CreateMessage
对象?我尝试了示例 here and here,但他们没有解组嵌套的原始 json 数据,而这正是我想要做的。
问题只是 CreateMessage
结构的 id
字段未导出,它以小写字母开头。将其更改为:
type CreateMessage struct {
Id int
}
它会起作用。
备注:
因为message2
已经是一个指针(new(CreateMessage)
),所以不用把它的地址传给json.Unmarshal()
,它的值就够了:
var message2 = new(CreateMessage)
if err := json.Unmarshal(message.Data, message2); err != nil {
panic(err)
}
log.Printf("%+v", message2)
输出:
2009/11/10 23:00:00 &{Id:5}
或者根本不使用 new()
:
var message2 CreateMessage
if err := json.Unmarshal(message.Data, &message2); err != nil {
panic(err)
}
log.Printf("%+v", message2)
输出:
2009/11/10 23:00:00 {Id:5}
在 Go Playground 上试用。
另请注意,现在字段名称为 "Id"
,JSON 包含 "id"
,但 json
包 "intelligent" 足以匹配它们(与 "Event"
和 "event"
相同)。但是要知道,如果您尝试编组您的结构,输出将包含 "Id"
而不是 "id"
.
如果您想使用完全不同的字段名称或确保在编组结构时将其小写,您可以使用 struct tags 来说明它在 JSON 文本中的显示方式,例如:
type CreateMessage struct {
MyId int `json:"id"`
}
我无法思考如何解组来自先前解组的 json 字节数组的原始 json 字符串。我有当前代码:
type Message struct {
Event string
Data json.RawMessage // how data is parsed depends on the event
}
type CreateMessage struct {
id int
}
var evt = []byte(`{"event": "create", "data" :{"id":5 }}`)
func main() {
var message Message
log.Println(string(evt))
json.Unmarshal(evt, &message)
log.Println(message)
log.Println(message.Event)
log.Println(string(message.Data))
fmt.Printf("%+v\n", message)
var message2 = new(CreateMessage)
err := json.Unmarshal( message.Data, &message2 )
log.Println(message2)
log.Println(err)
}
输出为:
2015/06/29 23:22:10 {"event": "create", "data" :{"id":5 }}
2015/06/29 23:22:10 {create [123 34 105 100 34 58 53 32 125]}
2015/06/29 23:22:10 create
2015/06/29 23:22:10 {"id":5 }
{Event:create Data:[123 34 105 100 34 58 53 32 125]}
2015/06/29 23:22:10 &{0}
2015/06/29 23:22:10 <nil>
为什么我不能将数据解组为 CreateMessage
对象?我尝试了示例 here and here,但他们没有解组嵌套的原始 json 数据,而这正是我想要做的。
问题只是 CreateMessage
结构的 id
字段未导出,它以小写字母开头。将其更改为:
type CreateMessage struct {
Id int
}
它会起作用。
备注:
因为message2
已经是一个指针(new(CreateMessage)
),所以不用把它的地址传给json.Unmarshal()
,它的值就够了:
var message2 = new(CreateMessage)
if err := json.Unmarshal(message.Data, message2); err != nil {
panic(err)
}
log.Printf("%+v", message2)
输出:
2009/11/10 23:00:00 &{Id:5}
或者根本不使用 new()
:
var message2 CreateMessage
if err := json.Unmarshal(message.Data, &message2); err != nil {
panic(err)
}
log.Printf("%+v", message2)
输出:
2009/11/10 23:00:00 {Id:5}
在 Go Playground 上试用。
另请注意,现在字段名称为 "Id"
,JSON 包含 "id"
,但 json
包 "intelligent" 足以匹配它们(与 "Event"
和 "event"
相同)。但是要知道,如果您尝试编组您的结构,输出将包含 "Id"
而不是 "id"
.
如果您想使用完全不同的字段名称或确保在编组结构时将其小写,您可以使用 struct tags 来说明它在 JSON 文本中的显示方式,例如:
type CreateMessage struct {
MyId int `json:"id"`
}