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
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t := reflect.TypeOf(record)
|
||||||
|
if t.Kind() == reflect.Ptr {
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
info := structs.GetTagInfo(t)
|
||||||
|
|
||||||
for _, fieldName := range idFieldNames {
|
for _, fieldName := range idFieldNames {
|
||||||
// Remove any ID field that was not set:
|
// Remove any ID field that was not set:
|
||||||
if reflect.ValueOf(recordMap[fieldName]).IsZero() {
|
if reflect.ValueOf(recordMap[fieldName]).IsZero() {
|
||||||
|
@ -569,7 +575,12 @@ func buildInsertQuery(
|
||||||
params = make([]interface{}, len(recordMap))
|
params = make([]interface{}, len(recordMap))
|
||||||
valuesQuery := make([]string, len(recordMap))
|
valuesQuery := make([]string, len(recordMap))
|
||||||
for i, col := range columnNames {
|
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)
|
valuesQuery[i] = dialect.Placeholder(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,7 +735,7 @@ func parseInputFunc(fn interface{}) (reflect.Type, error) {
|
||||||
|
|
||||||
type nopScanner struct{}
|
type nopScanner struct{}
|
||||||
|
|
||||||
var nopScannerValue = reflect.ValueOf(&nopScanner{})
|
var nopScannerValue = reflect.ValueOf(&nopScanner{}).Interface()
|
||||||
|
|
||||||
func (nopScanner) Scan(value interface{}) error {
|
func (nopScanner) Scan(value interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
|
@ -757,10 +768,13 @@ func scanRows(rows *sql.Rows, record interface{}) error {
|
||||||
|
|
||||||
valueScanner := nopScannerValue
|
valueScanner := nopScannerValue
|
||||||
if fieldInfo.Valid {
|
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...)
|
return rows.Scan(scanArgs...)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package structs
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
@ -16,6 +17,7 @@ type fieldInfo struct {
|
||||||
Name string
|
Name string
|
||||||
Index int
|
Index int
|
||||||
Valid bool
|
Valid bool
|
||||||
|
SerializeAsJSON bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s structInfo) ByIndex(idx int) *fieldInfo {
|
func (s structInfo) ByIndex(idx int) *fieldInfo {
|
||||||
|
@ -296,9 +298,17 @@ func getTagNames(t reflect.Type) structInfo {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tags := strings.Split(name, ",")
|
||||||
|
serializeAsJSON := false
|
||||||
|
if len(tags) > 1 {
|
||||||
|
name = tags[0]
|
||||||
|
serializeAsJSON = tags[1] == "json"
|
||||||
|
}
|
||||||
|
|
||||||
info.Add(fieldInfo{
|
info.Add(fieldInfo{
|
||||||
Name: name,
|
Name: name,
|
||||||
Index: i,
|
Index: i,
|
||||||
|
SerializeAsJSON: serializeAsJSON,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue