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

go-gorm postgres 方言:管理 jsonb 插入和查找的结构以正确使用 json 标签

go-gorm postgres 方言:管理 jsonb 插入和查找的结构以正确使用 json 标签

Go
拉丁的传说 2023-07-17 17:07:41
做了很多搜索,尽管我可以找到很多很好的文章来解释如何直接使用 pq 包。我对 go-gorm 和 postgresql 方言的工作感到茫然。如果在checks.go中我使用ChecksMap,它不会让我插入,但会让我找到。如果我使用postgres.jsonb它可以让我插入和查询,但找到的记录将是 jsonb。Gorm 使用指针的结构来确定数据库表和模式。当使用从 API 返回 json 响应的通用 searchHandler 实用程序时,这会引起头痛。对于任何非 jsonb 类型,gorm 使用正确的结构并使用 json 标签,但对于 jsonb,因为它没有对 jsonb 的“结构”的引用,所以不能使用 json 标签。这会导致返回 API json 的键大写。{   results: {      id: "123",      someId: "456",      results: [         {            Description: "foobar"         }      ]   }}是否有一种优雅的方法来处理此类事情,以便 jsonb 结果列具有正确的结构并使用小写的 json 标签?我只是想做一些在 go-gorm 的背景下不应该做的事情吗?PostgreSQL DDLCREATE TABLE checks (   id        text,   some_id   text,   results   jsonb);检查.gotype CheckRules struct {   Description   string `json:"description"`}type ChecksMap   map[string]CheckRulestype Checks struct {   ID            string           `gorm: "primary_key", json:"id"`   SomeID        *string          `json:"someId"`   Results       postgres.jsonb   `json:"results"`                   // <-- this   // results    ChecksMap        `gorm:"type:jsonb" json:"results"` // <-- or this}// func (cm *ChecksMap) Value() (driver.Value, error) {...}// func (cm *ChecksMap) Scan(val interface{}) error {...}insertChecks.govar resultsVal = getResultsValue() // simplifiedresJson, _ := json.Marshal(resultsVal)checks := Checks{   SomeID: "123",   Results: postgres.Jsonb{ RawMessage: json.RawMessage(resJson) }}err := db.Create(&checks).Error// ... some error handlinggetChecks.govar checks Checkserr := db.Find(&checks).Error// ... some error handling搜索处理程序func SearchHandler(db *gorm.DB, model, results interface{}) func(c echo.Context) error {   return func(c echo.Context) error {      err := db.Find(results).Error      // ... some error handling      jsnRes, _ := json.Marshal(results) // <-- uppercase "keys"      return c.JSON(http.StatusOK, struct {         Results interface{} `json:"results"`      }{         Results: string(jsnRes),      })   }}
查看完整描述

1 回答

?
米脂

TA贡献1836条经验 获得超3个赞

您可以使用自定义类型,但在其值接收器而不是指针接收器上ChecksMap实现接口。driver.Valuer


所以,而不是:


func (cm *ChecksMap) Value() (driver.Value, error) { ...

你会这样写:


func (cm ChecksMap) Value() (driver.Value, error) {

    if cm == nil {

        return nil, nil

    }

    return json.Marshal(cm)

}

或者,您可以使其与指针实现一起使用,但随后您必须将该字段转换为指针,例如:


type Checks struct {

   ID      string     `gorm: "primary_key", json:"id"`

   SomeID  *string    `json:"someId"`

   Results *ChecksMap `json:"results"`

}

(虽然我还没有测试过,所以我不能 100% 确定 gorm 将如何处理这种情况)


查看完整回答
反对 回复 2023-07-17
  • 1 回答
  • 0 关注
  • 222 浏览
慕课专栏
更多

添加回答

举报

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