go version)?go version go1.13 darwin/amd64
PostgreSQL 11.5
transaction.go
type FTransaction struct {
TxID string `json:"txId" gorm:"primary_key;unique;not null"`
Inputs []*InputOutput `json:"inputs"`
Outputs []*InputOutput `json:"outputs"`
}
type InputOutput struct {
Address string `json:"address"`
Amount int64 `json:"amount"`
}
Database
CREATE TABLE f_transactions(
tx_id VARCHAR(64) UNIQUE NOT NULL,
inputs JSONB,
outputs JSONB,
CONSTRAINT f_transactions_tx_id_key PRIMARY KEY(tx_id)
);
db.go
func (c *Context) CreateFTransaction(ftx *model.FTransaction) error {
if err := c.db.FirstOrCreate(&ftx).Error; err != nil {
return err
}
return nil
}
What works:
– Database entry created
What doesn't work:
– inputs & outputs fields are saved as NULL
Question:
I want to store inputs & outputs of transaction as JSONB fields into Postgres DB.
Is it possible with GORM?
I tried gorm:"json", sql:"json", sql:"json" – no success.
Will be appreciated for help.
Thank you!
me too~
You can implement the interface driver.Valuer to convert the structure to the value actually stored in the database, and implement the interfacedriver.Scanner to read the database value into the structure.
For gorm, implementing driver.Scanner is the only way to mark fields of type struct as normal, of course, except for the built-in typetime.Time.
type InputOutputs []*InputOutput
func (j InputOutputs) Value() (driver.Value, error) {
content, err := json.Marshal(j)
if err != nil {
return nil, err
}
return content, err
}
func (j *InputOutputs) Scan(value interface{}) error {
if value == nil {
*j = nil
return nil
}
s, ok := value.([]byte)
if !ok {
return fmt.Errorf("Invalid Scan Source")
}
if err := json.Unmarshal(s, j); err != nil {
return err
}
return nil
}
gorm related source code can be found here: ➡️
@sswanv do you use any gorm tags with that?
@bumberboy no, no tags required for @sswanv's solution.
Most helpful comment
You can implement the interface
driver.Valuerto convert the structure to the value actually stored in the database, and implement the interfacedriver.Scannerto read the database value into the structure.For gorm, implementing
driver.Scanneris the only way to mark fields of type struct as normal, of course, except for the built-in typetime.Time.gorm related source code can be found here: ➡️