forked from Mirrors/jsonapi
149 lines
3.3 KiB
Go
149 lines
3.3 KiB
Go
|
package jsonapi
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"reflect"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
func UnmarshalJsonApiPayload(payload *JsonApiPayload, model interface{}) error {
|
||
|
data := payload.Data
|
||
|
|
||
|
modelType := reflect.TypeOf(model).Elem()
|
||
|
modelValue := reflect.ValueOf(model).Elem()
|
||
|
|
||
|
var i = 0
|
||
|
var er error
|
||
|
modelType.FieldByNameFunc(func(name string) bool {
|
||
|
fieldType := modelType.Field(i)
|
||
|
fieldValue := modelValue.Field(i)
|
||
|
|
||
|
i += 1
|
||
|
|
||
|
tag := fieldType.Tag.Get("jsonapi")
|
||
|
|
||
|
args := strings.Split(tag, ",")
|
||
|
|
||
|
if len(args) >= 1 && args[0] != "" {
|
||
|
annotation := args[0]
|
||
|
|
||
|
if annotation == "primary" {
|
||
|
if len(args) >= 2 {
|
||
|
if data.Type != args[1] {
|
||
|
er = errors.New("Trying to Unmarshal a type that does not match")
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if fieldValue.Kind() == reflect.String {
|
||
|
fieldValue.Set(reflect.ValueOf(data.Id))
|
||
|
} else if fieldValue.Kind() == reflect.Int {
|
||
|
id, err := strconv.Atoi(data.Id)
|
||
|
if err != nil {
|
||
|
er = err
|
||
|
return false
|
||
|
}
|
||
|
fieldValue.SetInt(int64(id))
|
||
|
} else {
|
||
|
er = errors.New("Unsuppored data type for primary key, not int or string")
|
||
|
return false
|
||
|
}
|
||
|
} else {
|
||
|
er = errors.New("'type' as second argument required for 'primary'")
|
||
|
return false
|
||
|
}
|
||
|
} else if annotation == "attr" {
|
||
|
attributes := data.Attributes
|
||
|
if attributes == nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if len(args) >= 2 {
|
||
|
val := attributes[args[1]]
|
||
|
|
||
|
if fieldValue.Type() == reflect.TypeOf(time.Time{}) {
|
||
|
if reflect.TypeOf(val).Kind() != reflect.String {
|
||
|
er = errors.New("Cannot parse anything but string to Time")
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
t, err := time.Parse(time.RFC3339, reflect.ValueOf(val).String())
|
||
|
if err != nil {
|
||
|
er = err
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
fieldValue.Set(reflect.ValueOf(t))
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
fieldValue.Set(reflect.ValueOf(val))
|
||
|
} else {
|
||
|
er = errors.New("Attribute key required as second arg")
|
||
|
}
|
||
|
}
|
||
|
//} else if annotation == "relation" {
|
||
|
|
||
|
//isSlice := fieldValue.Type().Kind() == reflect.Slice
|
||
|
|
||
|
//if (isSlice && fieldValue.Len() < 1) || (!isSlice && fieldValue.IsNil()) {
|
||
|
//return false
|
||
|
//}
|
||
|
|
||
|
//if node.Relationships == nil {
|
||
|
//node.Relationships = make(map[string]interface{})
|
||
|
//}
|
||
|
|
||
|
//if included == nil {
|
||
|
//included = make([]*JsonApiNode, 0)
|
||
|
//}
|
||
|
|
||
|
//if isSlice {
|
||
|
//relationship, err := visitModelNodeRelationships(args[1], fieldValue)
|
||
|
|
||
|
//if err == nil {
|
||
|
//shallowNodes := make([]*JsonApiNode, 0)
|
||
|
//for k, v := range relationship {
|
||
|
//for _, node := range v {
|
||
|
//included = append(included, node)
|
||
|
|
||
|
//shallowNode := *node
|
||
|
//shallowNode.Attributes = nil
|
||
|
//shallowNodes = append(shallowNodes, &shallowNode)
|
||
|
//}
|
||
|
|
||
|
//node.Relationships[k] = shallowNodes
|
||
|
//}
|
||
|
//} else {
|
||
|
//err = err
|
||
|
//}
|
||
|
//} else {
|
||
|
//relationship, _, err := visitModelNode(fieldValue.Interface())
|
||
|
//if err == nil {
|
||
|
//shallowNode := *relationship
|
||
|
//shallowNode.Attributes = nil
|
||
|
|
||
|
//included = append(included, relationship)
|
||
|
|
||
|
//node.Relationships[args[1]] = &shallowNode
|
||
|
//} else {
|
||
|
//err = err
|
||
|
//}
|
||
|
//}
|
||
|
|
||
|
//} else {
|
||
|
//err = errors.New(fmt.Sprintf("Unsupported jsonapi tag annotation, %s", annotation))
|
||
|
//}
|
||
|
}
|
||
|
|
||
|
return false
|
||
|
})
|
||
|
|
||
|
if er != nil {
|
||
|
return er
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|