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