mirror of https://github.com/VinGarcia/ksql.git
Add feature for automatically serialize fields tagged as "*,json"
This commit implements the features, but it still needs tests to confirm it is working.pull/2/head
parent
f5b7ab8028
commit
3faaa4d152
|
@ -0,0 +1,30 @@
|
|||
package kissorm
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
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 {
|
||||
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) {
|
||||
return json.Marshal(j.Attr)
|
||||
}
|
22
kiss_orm.go
22
kiss_orm.go
|
@ -554,6 +554,12 @@ func buildInsertQuery(
|
|||
return "", nil, err
|
||||
}
|
||||
|
||||
t := reflect.TypeOf(record)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
info := structs.GetTagInfo(t)
|
||||
|
||||
for _, fieldName := range idFieldNames {
|
||||
// Remove any ID field that was not set:
|
||||
if reflect.ValueOf(recordMap[fieldName]).IsZero() {
|
||||
|
@ -569,7 +575,12 @@ func buildInsertQuery(
|
|||
params = make([]interface{}, len(recordMap))
|
||||
valuesQuery := make([]string, len(recordMap))
|
||||
for i, col := range columnNames {
|
||||
params[i] = recordMap[col]
|
||||
recordValue := recordMap[col]
|
||||
params[i] = recordValue
|
||||
if info.ByName(col).SerializeAsJSON {
|
||||
params[i] = jsonSerializable{Attr: recordValue}
|
||||
}
|
||||
|
||||
valuesQuery[i] = dialect.Placeholder(i)
|
||||
}
|
||||
|
||||
|
@ -724,7 +735,7 @@ func parseInputFunc(fn interface{}) (reflect.Type, error) {
|
|||
|
||||
type nopScanner struct{}
|
||||
|
||||
var nopScannerValue = reflect.ValueOf(&nopScanner{})
|
||||
var nopScannerValue = reflect.ValueOf(&nopScanner{}).Interface()
|
||||
|
||||
func (nopScanner) Scan(value interface{}) error {
|
||||
return nil
|
||||
|
@ -757,10 +768,13 @@ func scanRows(rows *sql.Rows, record interface{}) error {
|
|||
|
||||
valueScanner := nopScannerValue
|
||||
if fieldInfo.Valid {
|
||||
valueScanner = v.Field(fieldInfo.Index).Addr()
|
||||
valueScanner = v.Field(fieldInfo.Index).Addr().Interface()
|
||||
if fieldInfo.SerializeAsJSON {
|
||||
valueScanner = jsonSerializable{Attr: valueScanner}
|
||||
}
|
||||
}
|
||||
|
||||
scanArgs = append(scanArgs, valueScanner.Interface())
|
||||
scanArgs = append(scanArgs, valueScanner)
|
||||
}
|
||||
|
||||
return rows.Scan(scanArgs...)
|
||||
|
|
|
@ -3,6 +3,7 @@ package structs
|
|||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -13,9 +14,10 @@ type structInfo struct {
|
|||
}
|
||||
|
||||
type fieldInfo struct {
|
||||
Name string
|
||||
Index int
|
||||
Valid bool
|
||||
Name string
|
||||
Index int
|
||||
Valid bool
|
||||
SerializeAsJSON bool
|
||||
}
|
||||
|
||||
func (s structInfo) ByIndex(idx int) *fieldInfo {
|
||||
|
@ -296,9 +298,17 @@ func getTagNames(t reflect.Type) structInfo {
|
|||
continue
|
||||
}
|
||||
|
||||
tags := strings.Split(name, ",")
|
||||
serializeAsJSON := false
|
||||
if len(tags) > 1 {
|
||||
name = tags[0]
|
||||
serializeAsJSON = tags[1] == "json"
|
||||
}
|
||||
|
||||
info.Add(fieldInfo{
|
||||
Name: name,
|
||||
Index: i,
|
||||
Name: name,
|
||||
Index: i,
|
||||
SerializeAsJSON: serializeAsJSON,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue