Как преобразовать строку в sqlx.types.JSONText?
Я использую
gqlgen
,
sqlx
и
pgx
. Попытка использовать собственный скаляр для хранения в качестве типа jonb в базе данных postgres.
// graph/model/item.go
type Attributes types.JSONText
// Marshal here
...
func (a *Attributes) UnmarshalGQL(v interface{}) error {
switch v := v.(type) {
case []byte:
log.Println(" >> unmarshal.byte:", v)
json.Unmarshal(v, &a)
return nil
case string:
log.Println(" >> unmarshal.string:", v) // >> unmarshal.string: {"target": "localhost"}
json.Unmarshal([]byte(v), a) // This gives `null` in postgres
log.Println(" >> unmarshal.aT:", reflect.TypeOf(a)) // >> unmarshal.aT: *model.Attributes
log.Println(" >> unmarshal.aV:", reflect.ValueOf(a)) // >> unmarshal.aV: &[]
return nil
default:
return errors.New(fmt.Sprintf("Unsupported type: %T", v))
}
}
Желаемый результат
a *Attributes
должно быть
{"target": "localhost"}
, чтобы сохранить как jsonb в postgres:
| id | quantity | attributes |
|----|----------|-------------------------|
| 1 | 5 | {"target": "localhost"}|
Что я делаю не так?
Изменить: добавить образец мутации.
Это пример мутации:
mutation itemCreate {
itemCreate(input: {
quantity: 5,
attributes: "{\"target\": \"localhost\"}"
})
}
Изменить: добавить запрос sqlx.
Запрос для вставки:
func (d *ItemDb) ItemCreate(i *model.ItemInput) (*model.Item, error) {
log.Println(" >> i.Attributes:", i.Attributes) // >> i.Attributes: &[123 34 116 97 114 103 101 116 34 58 32 34 108 111 99 97 108 104 111 115 116 34 125]
item := &model.Item{}
if err := d.Get(item, `INSERT INTO items
(quantity, attributes)
VALUES ($1, $2)
RETURNING *`, i.Quantity, i.Attributes); err != nil {
return nil, err
}
return item, nil
}
1 ответ
Решение
Если
v
содержит буквальный json либо в
[]byte
или же
string
тогда нет необходимости в
json.Unmarshal
, все, что потребуется, это преобразование.
func (a *Attributes) UnmarshalGQL(v interface{}) error {
switch v := v.(type) {
case []byte:
*a = Attributes(v)
case string:
*a = Attributes(v)
default:
return errors.New(fmt.Sprintf("Unsupported type: %T", v))
}
return nil
}