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字段存储的是第三方透传参数,则其格式就不是固定的,本方法则不适用。

相关推荐
mit6.8243 小时前
[OP-Agent] 可扩展架构 | 插件管理器plugins.go
go·1024程序员节
无心水4 小时前
深入Java线程池:BlockingQueue实现全景解析与实战指南
java·后端·面试
Java水解4 小时前
Rust 性能优化实战:从 unsafe 使用到 SIMD 指令,让服务端响应快 2 倍
后端·rust
Java水解4 小时前
JAVA面试题大全(200+道题目)
java·后端·面试
卷福同学4 小时前
AI浏览器comet拉新,一单20美元(附详细教程)
人工智能·后端
大鱼七成饱4 小时前
掌握 anyhow,让你的 Rust 错误处理优雅又安全
后端·rust
2301_772093564 小时前
高并发webserver_interview
运维·服务器·数据库·后端·网络协议·mysql·wireshark
HashTang4 小时前
不用再配服务器了!这套 Next.js + Cloudflare 模板,一个人搞定全栈出海
前端·后端·边缘计算
水淹萌龙6 小时前
玩转 Go 表达式引擎:expr 实战指南
开发语言·后端·golang