Working with Postgres JSONB in Go

Background

Suppose I want to store and read a JSONB/JSON column from Postgres, how do I do it?

Solution

Make the data type implements these functions:

  • Scan(src any) error -> Move data from DB to Go struct
  • Value() -> Return the JSON encoding that stored in DB

Example

Suppose we have a product that contains some metadata like product width and length.

Option 1: If the JSON structure is known

type Product struct {
    Code     string
    Metadata Metadata
}

type Metadata struct {
    Width  int `json:"width"`
    Length int `json:"length"`
}

func (m *Metadata) Scan(value interface{}) error {
    return json.Unmarshal(value.([]byte), m)
}

func (m *Metadata) Value() (driver.Value, error) {
    return json.Marshal(m)
}

Option 2: Unknown JSON structure

type Product struct {
    Code     string
    Metadata Metadata
}

type Metadata map[string]interface{}

func (m *Metadata) Scan(value interface{}) error {
    return json.Unmarshal(value.([]byte), m)
}

func (m *Metadata) Value() (driver.Value, error) {
    return json.Marshal(m)
}

Trade-off:

❌ Need to type assert before using the value