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

相关推荐
IT_陈寒2 小时前
React的状态更新坑得我差点加班到天亮
前端·人工智能·后端
明月_清风2 小时前
从二叉树到 B+ 树:一文搞懂工程中「树」的演化之道
数据结构·算法·go
码事漫谈3 小时前
一天搭出 80% 的 Agent,然后卡在 95% 到死
后端
leonkay3 小时前
C# 锁机制——【2】深入原理
开发语言·后端·spring·c#·个人开发
江湖十年3 小时前
在 Go 中使用 dyno 包处理动态对象
后端·面试·go
a187927218313 小时前
【算法】回溯算法(三):三记重锤与 N 皇后——记忆化、状态设计与三层漏斗
算法·leetcode·go·剪枝·回溯·n皇后·算法讲解
八角丶3 小时前
Node 网络编程 —— TLS 模块
javascript·后端·node.js
山岚的运维笔记3 小时前
mysql 专业笔记 -- 第 8 章:使用变量
运维·数据库·笔记·后端·学习·mysql·dba
纪卓志George4 小时前
打破语言范式:在 Go 里用动态代理实现 AOP
架构·go
平头哥AI5 小时前
Day 01 | go run 跑通第一个 Go 程序,go build 留下一个能拷走的 exe
开发语言·后端·golang