package ksql import ( "database/sql/driver" "encoding/json" "fmt" "reflect" ) // This type was created to make it easier to adapt // input attributes to be convertible to and from JSON // before sending or receiving it from the database. type jsonSerializable struct { DriverName string Attr interface{} } // Scan Implements the Scanner interface in order to load // this field from the JSON stored in the database func (j *jsonSerializable) Scan(value interface{}) error { if value == nil { v := reflect.ValueOf(j.Attr) // Set the struct to its 0 value just like json.Unmarshal // does for nil attributes: v.Elem().Set(reflect.Zero(reflect.TypeOf(j.Attr).Elem())) return nil } // Required since sqlite3 returns strings not bytes if v, ok := value.(string); ok { value = []byte(v) } rawJSON, ok := value.([]byte) if !ok { return fmt.Errorf("unexpected type received to Scan: %T", value) } return json.Unmarshal(rawJSON, j.Attr) } // Value Implements the Valuer interface in order to save // this field as JSON on the database. func (j jsonSerializable) Value() (driver.Value, error) { b, err := json.Marshal(j.Attr) if j.DriverName == "sqlserver" { return string(b), err } return b, err }