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

使用 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 数据?



白猪掌柜的
浏览 140回答 2
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以了解我是如何做到的,但这完全是未完成 我只实现了我在做某事时需要的部分。

心有法竹

事实证明,最简单的方法是在 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)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go