package goneo
import (
"fmt"
"reflect"
"strings"
)
func unmarshal(data map[string]interface{}, out interface{}) error {
val := reflect.ValueOf(out).Elem()
valE := val
valV := val
switch valE.Kind() {
case reflect.Ptr, reflect.Interface:
valE = valE.Elem()
valV = valV.Elem()
}
tmp := reflect.New(valE.Type()).Elem()
tmp.Set(valV)
defer val.Set(tmp)
repr := getTagsRepresentation(out)
for k, v := range data {
entry := repr[k]
k = entry.FieldName
// Ignored
if !entry.Enabled {
continue
}
// omitEmpty
if entry.Attributes[omitEmpty] {
if isZero(v) {
continue
}
}
tmp.FieldByName(k).Set(reflect.ValueOf(v))
}
return nil
}
func marshal(in interface{}) string {
var out []string
val := reflect.ValueOf(in)
typ := reflect.TypeOf(in)
switch typ.Kind() {
case reflect.Slice, reflect.Array:
panic("only single & pointer types of structs are currently supported")
case reflect.Ptr, reflect.Interface:
typ = typ.Elem()
val = val.Elem()
}
repr := getTagsRepresentation(in)
for i := 0; i < typ.NumField(); i++ {
fld := typ.Field(i)
entry := repr[fld.Name]
fldV := val.FieldByName(fld.Name).Interface()
// Ignored
if !entry.Enabled {
continue
}
// omitEmpty
if entry.Attributes[omitEmpty] {
if isZero(fldV) {
continue
}
}
out = append(out, fmt.Sprintf(`%s: "%v"`, entry.Identifier, fldV))
}
return fmt.Sprintf("{ %s }", strings.Join(out, ", "))
}
func identifier(i interface{}) string {
rValue := reflect.TypeOf(i)
switch rValue.Kind() {
case reflect.Ptr, reflect.Interface:
rValue = rValue.Elem()
}
return strings.ToLower(rValue.Name())
}
func identifierWithSuffix(i interface{}, suffix string) string {
return fmt.Sprintf("%s%s", identifier(i), suffix)
}
func marshalToMap(in interface{}) (out map[string]interface{}) {
out = make(map[string]interface{})
val := reflect.ValueOf(in)
switch val.Kind() {
case reflect.Ptr, reflect.Interface:
val = val.Elem()
}
repr := getTagsRepresentation(in)
for i := 0; i < val.NumField(); i++ {
entry := repr[val.Type().Field(i).Name]
fldV := val.Field(i).Interface()
// Ignored
if !entry.Enabled {
continue
}
// omitEmpty
if entry.Attributes[omitEmpty] {
if isZero(fldV) {
continue
}
}
out[entry.Identifier] = fldV
}
return
}
func returns(i interface{}) string {
var out []string
for k, _ := range marshalToMap(i) {
out = append(out, fmt.Sprintf("%s.%s", identifier(i), k))
}
return strings.Join(out, ", ")
}
func filter(i interface{}) string {
var attrs []string
for k, v := range marshalToMap(i) {
attrs = append(attrs, fmt.Sprintf(`(%s.%s = "%s")`, strings.ToLower(identifier(i)), k, v))
}
return strings.Join(attrs, " AND ")
}
func filterWithSuffix(i interface{}, suffix string) string {
var attrs []string
for k, v := range marshalToMap(i) {
attrs = append(attrs, fmt.Sprintf(`(%s.%s = "%s")`, strings.ToLower(identifierWithSuffix(i, suffix)), k, v))
}
return strings.Join(attrs, " AND ")
}
func finder(i interface{}) string {
var attrs []string
for k, v := range marshalToMap(i) {
attrs = append(attrs, fmt.Sprintf(`(%s.%s = "%s")`, strings.ToLower(identifier(i)), k, v))
}
return strings.Join(attrs, " OR ")
}
func isZero(i interface{}) bool {
if i == nil {
return true
}
typ := reflect.TypeOf(i)
switch typ.Kind() {
case reflect.Ptr, reflect.Interface:
if reflect.ValueOf(i).IsNil() {
return true
}
}
val := reflect.ValueOf(&i).Elem()
if i == nil || val.IsNil() {
return true
}
return asRef(val).IsZero()
}
func asRef(val reflect.Value) reflect.Value {
switch val.Kind() {
case reflect.Interface, reflect.Ptr:
val = val.Elem()
}
if val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
return asRef(val.Elem())
}
return val
}
func asRefType(typ reflect.Type) reflect.Type {
switch typ.Kind() {
case reflect.Interface, reflect.Ptr:
typ = typ.Elem()
}
if typ.Kind() == reflect.Interface || typ.Kind() == reflect.Ptr {
return asRefType(typ)
}
return typ
}
|
The pages are generated with Golds v0.4.2. (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |