使用GORM插入含pgtype.JSONB字段的结构体触发SQL 22P02错误
问题分析
你遇到的核心矛盾是:GORM打印的INSERT语句能直接在PostgreSQL中执行成功,但调用Create方法时却抛出JSON语法错误。这说明GORM实际执行时的参数绑定逻辑与打印的SQL不一致,问题根源出在pgtype.JSONB字段的处理环节。
可能的原因及解决方案
1. 明确指定GORM字段的JSONB类型
你的Config字段使用了pgtype.JSONB,但GORM可能未自动识别该字段的JSONB类型,导致参数绑定时错误序列化。修改结构体标签,明确声明字段类型:
type ComputeConfig struct { DbId DbOwnerAudit DbTimeAudit Name *string `gorm:"column:name" json:"name"` Type ComputeType `gorm:"column:type" json:"type"` Endpoint *string `gorm:"column:endpoint" json:"endpoint"` // 添加 type:jsonb 明确字段类型 Config *pgtype.JSONB `gorm:"column:config;type:jsonb" json:"config"` }
2. 确保pgtype.JSONB的Valid状态
pgtype系列类型依赖Valid字段标识值是否有效,如果该字段为false,GORM可能会将其序列化为空值或错误格式。修改ConvertMapToJSONB函数,强制设置Valid:
func ConvertMapToJSONB(data map[string]interface{}) (*pgtype.JSONB, error) { jsonData, err := json.Marshal(data) if err != nil { return nil, err } jsonb := &pgtype.JSONB{} err = jsonb.Set(jsonData) if err != nil { return nil, err } // 确保Valid为true(部分场景下Set方法不会自动设置) jsonb.Valid = true return jsonb, nil }
3. 替换pgtype.JSONB为原生类型简化处理
如果上述方法无效,可以放弃pgtype.JSONB,改用GORM原生支持的类型:
方案一:直接使用
map[string]interface{}
修改结构体字段:Config map[string]interface{} `gorm:"column:config;type:jsonb" json:"config"`此方式下GORM会自动将map序列化为JSONB,无需手动转换。
方案二:用
[]byte存储JSONConfig []byte `gorm:"column:config;type:jsonb" json:"config"`插入时直接传入
json.Marshal后的字节数组即可。
4. 升级GORM及PostgreSQL驱动版本
你使用的gorm.io/driver/postgres v1.5.11和gorm.io/gorm v1.25.12版本相对老旧,可能存在pgtype.JSONB的兼容性bug。升级到最新稳定版:
go get gorm.io/gorm@latest go get gorm.io/driver/postgres@latest
验证步骤
修改后重新测试:
- 调用
CreateConfig方法,观察GORM打印的SQL是否与之前一致 - 如果仍报错,查看错误详情中的完整JSON片段(当前错误仅显示
Token "" is invalid,大概率是实际传递的JSON为空或格式异常)
内容的提问来源于stack exchange,提问作者Kunal Katiyar
相关产品推荐
相关产品推荐

