When you need to handle text tags in Golang, eg. a Document
can be tagged with software engineering
, important
and golang
,
you could do it with the Postgres text[]
array type.
But with the jsonb
type, you have all the marshalling and unmarshalling already there, so all you need to do is have a []string
type,
like below:
type JSONTags []string
func (tags *JSONTags) Scan(src interface{}) error {
var jt types.JSONText
if err := jt.Scan(src); err != nil {
return err
}
if err := jt.Unmarshal(tags); err != nil {
return err
}
return nil
}
func (tags *JSONTags) Value() (driver.Value, error) {
var jt types.JSONText
data, err := json.Marshal((*[]string)(tags))
if err != nil {
return nil, err
}
if err := jt.UnmarshalJSON(data); err != nil {
return nil, err
}
return jt.Value()
}
func (tags *JSONTags) MarshalJSON() ([]byte, error) {
return json.Marshal((*[]string)(tags))
}
func (tags *JSONTags) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, (*[]string)(tags)); err != nil {
return err
}
return nil
}
Then you can use it in your struct like this:
type Document struct {
Title string `json:"title" db:"title"`
Tags *JSONTags `json:"tags" db:"tags"` // Note the pointer here
}
and you can unmarshal JSON like this into such a struct:
{
"title": "Go in Action",
"tags": ["software engineering", "important", "golang"]
}
and use the Document
with Get()
and Select()
in SQLX, and you can still use it in Golang like a regular slice.