[英][]string to jsonb with Gorm and postgres
I have a Go struct which contains a slice of strings which I'd like to save as a jsonB object in Postgres with GORM.我有一个 Go 结构,它包含一段字符串,我想用 GORM 在 Postgres 中将其保存为 jsonB 对象。
I've come accross a solution which requires to use the GORM specific type (postgres.Jsonb) which I'd like to avoid.我遇到了一个需要使用我想避免的 GORM 特定类型 (postgres.Jsonb) 的解决方案。
When I try to run the AutoMigrate with a slice in my model, it panics and won't start although when I wrap this slice in a struct (which I'm okay doing) it will run without error but won't create the column in postgres.当我尝试在我的模型中使用切片运行 AutoMigrate 时,它会出现恐慌并且不会启动,尽管当我将此切片包装在一个结构中(我可以这样做)时,它会正常运行但不会创建列在 postgres 中。
type User struct {
gorm.Model
Data []string `sql:"type:"jsonb"; json:"data"`
} //Panics
type User struct {
gorm.Model
Data struct {
NestedData []string
} `sql:"type:"jsonb"; json:"data"`
} //Doesn't crash but doesn't create my column
Has anyone been able to manipulate jsonb with GORM without using the postgres.Jsonb type in models ?有没有人能够在不使用模型中的 postgres.Jsonb 类型的情况下使用 GORM 操作 jsonb ?
Maybe:也许:
type DataJSONB []string
func (dj DataJSONB) Value() (driver.Value, error) {
return json.Marshal(dj)
}
func (dj *DataJSONB) Scan(value interface{}) error {
b, ok := value.([]byte)
if !ok {
return fmt.Errorf("[]byte assertion failed")
}
return json.Unmarshal(b, dj)
}
// Your bit
type User struct {
gorm.Model
Data DataJSONB `sql:"type:"jsonb"; json:"data"`
}
Define a new type:定义一个新类型:
type Data map[string]interface{}
And implement the Valuer
and Scanner
interfaces onto them, which allows the field to be converted to a value for the database, and scanned back into the field, respectively:并在它们上实现Valuer
和Scanner
接口,这允许将字段转换为数据库的值,并分别扫描回字段:
// Value converts into []byte
func (d Data) Value() (driver.Value, error) {
j, err := json.Marshal(d)
return j, err
}
// Scan puts the []byte back into Data
func (d *Data) Scan(src interface{}) error {
source, ok := src.([]byte)
if !ok {
return errors.New("Type assertion .([]byte) failed.")
}
var i interface{}
if err := json.Unmarshal(source, &i); err != nil {
return err
}
*d, ok = i.(map[string]interface{})
if !ok {
return errors.New("Type assertion .(map[string]interface{}) failed.")
}
return nil
}
Then you can define your field in your model like this:然后你可以在你的模型中定义你的字段,如下所示:
type User struct {
gorm.Model
Data Data `type: jsonb not null default '{}'::jsonb`
}
Using the underlying map[string]interface{}
type is nice too, as you can Unmarshal
/ Marshal
any JSON to/from it.使用底层的map[string]interface{}
类型也很好,因为您可以Unmarshal
/ Marshal
任何 JSON 到/从它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.