[] строка в jsonb с Gorm и postgres - PullRequest
       112

[] строка в jsonb с Gorm и postgres

0 голосов
/ 06 февраля 2020

У меня есть структура Go, которая содержит фрагмент строк, которые я хотел бы сохранить как объект jsonB в Postgres с GORM.

Я нашел решение, которое требует используйте тип GORMI c (postgres .Jsonb), которого я бы хотел избежать.

Когда я пытаюсь запустить 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

Кто-нибудь смог манипулировать jsonb с помощью GORM без использования типа postgres .Jsonb в моделях?

Ответы [ 2 ]

0 голосов
/ 26 февраля 2020

Может быть:

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"`
}
0 голосов
/ 26 февраля 2020

Определите новый тип:

type Data map[string]interface{}

И внедрите в них интерфейсы 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
}

Затем вы можете определить свое поле в вашей модели следующим образом:

type User struct {
        gorm.Model
        Data Data `type: jsonb not null default '{}'::jsonb`
}

Используя базовый * Тип 1016 * тоже хорош, так как вы можете Unmarshal / Marshal любой JSON в / из него.

...