为了账号安全,请及时绑定邮箱和手机立即绑定

反序列化嵌套的 JSON,或者直接在 Go 中传递它

反序列化嵌套的 JSON,或者直接在 Go 中传递它

Go
白猪掌柜的 2021-12-06 19:14:24
使用 Go 构建基本 API,我将 JSON 以及其他一些(普通)数据类型存储在 postgres 表的 JSON 字段中。使用我的模型,我只是尝试从数据库中获取一行并将其作为 JSON 转发。使用GORM将数据反序列化为一个结构体,大部分映射都是无缝发生的,除了 JSON,它取决于所选的数据类型,呈现为字节数组或字符串。以下是模型(更新):type Item struct {    --snip--    Stats []ItemInfo `gorm:"column:stats" json:"stats" sql:"json"`    --snip--}type ItemInfo struct {    Stat        string      `json:"stat"`    Amount      int         `json:"amount"`}典型的 JSON 看起来像这样(来自数据库):[{"stat": "Multistrike", "amount": 193}, {"stat": "Crit", "amount": 145},  {"stat": "Agility", "amount": 254}, {"stat": "Stamina", "amount": 381}]所以这个想法是我只想传递这些数据,而不是改变它,或者将它反序列化为 Go 结构或任何东西。控制器/路由如下:func GetItem(c *gin.Context) {    id, err := strconv.Atoi(c.Param("id"))    // Convert Parameter to int, for db query    if err != nil {        panic(err)    }    // Get the DB context    db, ok := c.MustGet("databaseConnection").(gorm.DB)    if !ok {        // Do something    }    // Hold the structified item here.    var returnedItem models.Item    // Get the db row    db.Where(&models.Item{ItemID: id}).First(&returnedItem)    if c.Bind(&returnedItem) == nil {        // Respond with the struct as json        c.JSON(http.StatusOK, returnedItem)    }}它以以下 JSON 响应(统计信息为 json.RawMessage):{    "context": "raid-finder",    "stats": "W3sic3RhdCI6ICJWZXJzYXRpbGl0eSIsICJhbW91bnQiOiA0NX0sIHsic3RhdCI6ICJDcml0IiwgImFtb3VudCI6IDEwMH0sIHsic3RhdCI6ICJBZ2lsaXR5IiwgImFtb3VudCI6IDEwOX0sIHsic3RhdCI6ICJTdGFtaW5hIiwgImFtb3VudCI6IDE2M31d",}或者(使用 stats 作为字符串):{    "context": "raid-finder",    "stats": "[{\"stat\": \"Versatility\", \"amount\": 45}, {\"stat\": \"Crit\", \"amount\": 100}, {\"stat\": \"Agility\", \"amount\": 109}, {\"stat\": \"Stamina\", \"amount\": 163}]",}我有什么选择可以简单地传递这个,到目前为止我没有成功地尝试将 JSON 映射到一个结构(由于动态数据,这变得困难,以及我选择 JSON 开始的原因)?我意识到gin-gonic有一些神奇之处,c.JSON 自动(?)将所有数据从结构编组到 JSON,但希望有某种方法可以避免编组 json 数据?
查看完整描述

2 回答

?
湖上湖

TA贡献2003条经验 获得超2个赞

制作一个像itemInfo或类似的子结构:


type itemInfo struct {

    Stat string `json:"stat"`

    Crit int    `json:"crit"`

}

然后在你的Item结构中


type Item struct {

    --snip--

    Context string `gorm:"column:context" json:"context"`

    Stats []itemInfo `gorm:"column:stats" json:"stats" sql:"json"`

    --snip--

}

然后当你解组它应该很好地进入项目信息!


此外,我假设您正在使用 blizzards API,我已经制作了一个包装器,您可以在此处查看:https : //github.com/Gacnt/Go-WoW-API以了解我是如何做到的,但这完全是未完成 我只实现了我在做某事时需要的部分。


查看完整回答
反对 回复 2021-12-06
?
心有法竹

TA贡献1866条经验 获得超5个赞

事实证明,最简单的方法是在 Item 结构中提供一个额外的属性,让 GORM 解组为 []byte,然后将字节数组解组为子结构:


// Item is a thing..

type Item 

    Stats           []byte    `gorm:"column:stats"  json:"stats"`

    StatsList       []ItemInfo `json:"iteminfo"`

}

并像这样解组它:


err = json.Unmarshal(returnedItem.Stats, &returnedItem.StatsList)


查看完整回答
反对 回复 2021-12-06
  • 2 回答
  • 0 关注
  • 139 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信