gorm读取PostgreSQL的json数据类型

一、背景和意义

使用gorm读取PostgreSQL中json/jsonb类型数据是一个常见的操作。本文介绍几种方法,适用于几类不同的场景。

二、常用方法

在本例中,数据库有一个表 test_tbl1,包含如下三个字段:

  • id,主键,长整型
  • params,jsonb类型
  • params2,json类型

接下来展示从该表中读取一行数据的几种方法:

2.1 方法一

go 复制代码
type TestTbl1 struct {
   ID      int64 `gorm:"primaryKey"`
   Params  string
   Params2 string
}

func main() {
    row := &TestTbl1{}
    var db *gorm.DB
    db = initDB()   // 初始化数据库连接的代码省略,可以查阅相关资料
    err := db.First(row).Error
    if err != nil {
       log.Error("fail to query test_tbl1: %v", err)
    }
    log.Infof("get data: %+v", row)
    log.Infof("get data: params: %+v", row.Params)
    log.Infof("get data: params2: %+v", row.Params2)
}

这是比较简单和适用性较强的方法,查出字符串之后再做解析。即使数据库的json/jonb字段格式不一致时,也能正常运行。

2.2 方法二

考虑到go中做json解析的方法是json.Unmarshal,该方法的参数是[]byte,为了方便做json解析,可以直接将字段类型从sting改为[]byte:

go 复制代码
type TestTbl1 struct {
   ID      int64 `gorm:"primaryKey"`
   Params  []byte
   Params2 []byte
}

func main() {
    row := &TestTbl1{}
    var db *gorm.DB
    db = initDB()   // 初始化数据库连接的代码省略,可以查阅相关资料
    err := db.First(row).Error
    if err != nil {
       log.Error("fail to query test_tbl1: %v", err)
    }
    log.Infof("get data: %+v", row)
    log.Infof("get data: params: %+v", string(row.Params))
    log.Infof("get data: params2: %+v", string(row.Params2))
}

2.3 方法三

如果json/jsonb字段的格式是固定的,可以在查询的时候自动做json解析。在本例中,假设param的取值示例为 {"k1": "v1", "k2": "v2"},param2的取值示例为["v1","v2","v3"],则相关代码如下:

go 复制代码
type StringArray []string

func (j *StringArray) Scan(value interface{}) error {
   return json.Unmarshal(value.([]byte), j)
}

func (j *StringArray) Value() (driver.Value, error) {
   return json.Marshal(j)
}

type JsonObject struct {
   K1 string
   K2 string
}

func (j *JsonObject) Scan(value interface{}) error {
   return json.Unmarshal(value.([]byte), j)
}

func (j *JsonObject) Value() (driver.Value, error) {
   return json.Marshal(j)
}

type TestTbl1 struct {
   ID      int64     `gorm:"primaryKey"`
   Params  JsonObject     `gorm:"type:jsonb"`
   Params2 StringArray `gorm:"type:json"`
}

func main() {
    row := &TestTbl1{}
    var db *gorm.DB
    db = initDB()   // 初始化数据库连接的代码省略,可以查阅相关资料
    err := db.First(row).Error
    if err != nil {
       log.Error("fail to query test_tbl1: %v", err)
    }
    log.Infof("get data: %+v", row)
    log.Infof("get data: params: %+v", row.Params)
    log.Infof("get data: params2: %+v", row.Params2)
}

这一种方法的普适性有限。例如,如果json/jsonb字段存储的是第三方透传参数,则其格式就不是固定的,本方法则不适用。

相关推荐
Cobyte11 分钟前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc
程序员侠客行1 小时前
Mybatis连接池实现及池化模式
java·后端·架构·mybatis
Honmaple1 小时前
QMD (Quarto Markdown) 搭建与使用指南
后端
PP东1 小时前
Flowable学习(二)——Flowable概念学习
java·后端·学习·flowable
invicinble2 小时前
springboot的核心实现机制原理
java·spring boot·后端
全栈老石2 小时前
Python 异步生存手册:给被 JS async/await 宠坏的全栈工程师
后端·python
space62123272 小时前
在SpringBoot项目中集成MongoDB
spring boot·后端·mongodb
Tony Bai3 小时前
再见,丑陋的 container/heap!Go 泛型堆 heap/v2 提案解析
开发语言·后端·golang
寻找奶酪的mouse3 小时前
30岁技术人对职业和生活的思考
前端·后端·年终总结
梦想很大很大3 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go