You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go使用pgx读取PostgreSQL的JSONB字段时如何定义结构体接收动态键

解决方案

方案1:使用map存储动态键值对(推荐)

因为user_roles下的键是动态的UID字符串,值为角色数组,直接将UserRoles字段声明为map[string][]string类型即可适配动态键:

type Data struct {
    UserRoles map[string][]string `json:"user_roles,omitempty"`
}
type MyTable struct {
    ID   string
    Data Data
}

方案2:适配pgx的JSONB反序列化逻辑

pgx默认无法直接将JSONB字段转换为自定义结构体,有两种处理方式可选:

方式A:先读取为字节数组再手动反序列化

import "encoding/json"

// ... 省略其他初始化代码

sql := "SELECT id, data FROM mytable" // 建议同时查询id字段
myTable := new(MyTable)
var dataBytes []byte
// 按查询字段顺序Scan
err = pg.QueryRow(context.Background(), sql).Scan(&myTable.ID, &dataBytes)
if err != nil {
    // 处理查询错误
}
// 反序列化字节数组为Data结构体
err = json.Unmarshal(dataBytes, &myTable.Data)
if err != nil {
    // 处理反序列化错误
}
fmt.Printf("%v", myTable.Data)

方式B:为Data类型实现pgx的Scanner接口

实现后可以直接将JSONB字段Scan到Data结构体,简化后续查询代码:

import (
    "encoding/json"
    "errors"
)

// 实现pgx Scanner接口
func (d *Data) Scan(src interface{}) error {
    source, ok := src.([]byte)
    if !ok {
        return errors.New("failed to assert src as []byte")
    }
    return json.Unmarshal(source, d)
}

// ... 后续查询可以直接Scan
sql := "SELECT id, data FROM mytable"
myTable := new(MyTable)
err = pg.QueryRow(context.Background(), sql).Scan(&myTable.ID, &myTable.Data)

其他可选方案

如果不需要结构化处理JSONB内容,仅需要完整返回原始JSON,可以直接将Data字段声明为[]byte或json.RawMessage类型,无需反序列化直接使用。


内容的提问来源于stack exchange,提问作者Hongbo Miao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 08:39:02