json - 读取json数据时动态识别对象类型
问题描述
很新,很抱歉,如果这个问题听起来很明显。
我想在读取 json 文件时使用反射来识别对象的类型。
用例(请参阅下面的代码)如下:我有两个包含不同字段的结构 BoyGift 和 GirlGift。我还有一个布尔指示符 IsBoy,如果礼物的接受者是男孩,则为 true,否则为 false。
封装此行为的类型是 Gift 类型:
//Gift type
type Gift struct {
IsBoy bool `json:"isBoy"`
Payload ??? `json:"payload"`
}
保存数据。如何定义该类型以使 json unmarshal 动态转换为正确的类型?在这种情况下,“json 模式”定义了 Gift 应该是 BoyGift 或 GirlGift。是否可以通过反射来做到这一点?如何?
如果布尔信息已知,则进行两次解组会很棒
package main
import (
"encoding/json"
"fmt"
)
//BoyGift type
type BoyGift struct {
Cars uint32 `json:"cars"`
Balls uint32 `json:"balls"`
}
//GirlGift type
type GirlGift struct {
Dolls uint32 `json:"dolls"`
Lego uint32 `json:"lego"`
}
//Gift type
type Gift struct {
IsBoy bool `json:"isBoy"`
Payload GirlGift `json:"payload"`
}
func main() {
b := []byte(`{
"isBoy": true,
"payload": {
"cars": 1,
"balls": 2
}
}`)
var g Gift
err := json.Unmarshal(b, &g)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(g)
}
解决方案
您应该使用json.RawMessage
动态解组数据。
您可以将 Gift 的 Payliad 定义为json.RawMessage
,然后延迟解组,直到您知道 的值IsBoy
。您可以在下面找到如何执行此操作的基本示例。
package main
import (
"encoding/json"
"fmt"
)
//BoyGift type
type BoyGift struct {
Cars uint32 `json:"cars"`
Balls uint32 `json:"balls"`
}
//GirlGift type
type GirlGift struct {
Dolls uint32 `json:"dolls"`
Lego uint32 `json:"lego"`
}
//Gift type
type Gift struct {
IsBoy bool `json:"isBoy"`
Payload json.RawMessage `json:"payload"`
}
func main() {
b1 := []byte(`{
"isBoy": true,
"payload": {
"cars": 1,
"balls": 2
}
}`)
b2 := []byte(`{
"isBoy": false,
"payload": {
"dolls": 3,
"lego": 4
}
}`)
for _, b := range [][]byte{b1, b2} {
var g Gift
err := json.Unmarshal(b, &g)
if err != nil {
fmt.Println(err)
return
}
if g.IsBoy {
var boyGift BoyGift
err := json.Unmarshal(g.Payload, &boyGift)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(boyGift)
} else {
var girlGift GirlGift
err := json.Unmarshal(g.Payload, &girlGift)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(girlGift)
}
}
}
如果您想Payload
用作interface{}
(可以是BoyGift
or GirlGift
),您可以创建额外的辅助结构来进行解组。检查 Go Playground 中的扩展示例:https: //play.golang.org/p/q1Hn45bgjsc
推荐阅读
- java - JAXB 解组性能改进?
- amazon-web-services - 带有 Transfer Acceleration 下载命令的 AWS S3 CLI 引发 400 错误:调用 HeadObject 操作时:错误请求
- html - Node.js Web Crawling - 如何在 HTML 中加载所有数据?
- html - How to fix the labels positioned wrong in my default Django form?
- soap - 从 jMeter 中的 SOAP 请求中删除空组
- android - EmbossMaskFilter 导致 Android OS 8.1(Oreo)、9.0(Pie) 上的 App 崩溃,其余工作正常
- stripe-payments - Ngrok - 带有虚拟主机的 HTTP 400
- android - 在片段活动上创建一个按钮
- php - 在 codeigniter 中使用 ajax 的可靠下拉列表不起作用
- android - kotlin - 解决 DataBindingUtil.setContentView() 中的错误