2017-09-16 16:02:26 +00:00
|
|
|
package jsonld
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2017-09-30 21:36:05 +00:00
|
|
|
"reflect"
|
2017-09-16 16:02:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type payloadWithContext struct {
|
2017-10-02 10:07:11 +00:00
|
|
|
Context *Context `json:"@context"`
|
2017-09-16 16:02:26 +00:00
|
|
|
Obj *interface{}
|
|
|
|
}
|
|
|
|
|
2017-10-01 11:43:36 +00:00
|
|
|
func IsEmpty(v reflect.Value) bool {
|
|
|
|
var ret bool
|
|
|
|
switch v.Kind() {
|
|
|
|
case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
|
|
|
|
ret = v.IsNil()
|
|
|
|
case reflect.Slice, reflect.Map:
|
|
|
|
ret = v.Len() == 0
|
2017-09-30 21:36:05 +00:00
|
|
|
case reflect.Struct:
|
2017-10-01 11:43:36 +00:00
|
|
|
ret = func(reflect.Value) bool {
|
|
|
|
var ret bool = true
|
|
|
|
for i := 0; i < v.NumField(); i++ {
|
|
|
|
ret = ret && IsEmpty(v.Field(i))
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}(v)
|
2017-09-30 21:36:05 +00:00
|
|
|
case reflect.String:
|
2017-10-01 11:43:36 +00:00
|
|
|
ret = v.String() == ""
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
|
ret = v.Int() == 0
|
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
|
|
ret = v.Uint() == 0
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
ret = v.Float() == 0.0
|
2017-09-30 21:36:05 +00:00
|
|
|
}
|
2017-10-01 11:43:36 +00:00
|
|
|
return ret
|
2017-09-30 21:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getMap(v interface{}) map[string]interface{} {
|
2017-09-16 16:02:26 +00:00
|
|
|
a := make(map[string]interface{})
|
2017-09-30 21:36:05 +00:00
|
|
|
typ := reflect.TypeOf(v)
|
|
|
|
val := reflect.ValueOf(v)
|
|
|
|
if typ.Kind() == reflect.Ptr {
|
|
|
|
typ = typ.Elem()
|
|
|
|
val = val.Elem()
|
|
|
|
}
|
2017-10-01 11:43:36 +00:00
|
|
|
|
2017-09-30 21:36:05 +00:00
|
|
|
for i := 0; i < typ.NumField(); i++ {
|
|
|
|
cField := typ.Field(i)
|
|
|
|
cValue := val.Field(i)
|
|
|
|
if cField.Anonymous {
|
|
|
|
for k, v := range getMap(cValue.Interface()) {
|
|
|
|
a[k] = v
|
|
|
|
}
|
|
|
|
} else {
|
2017-10-01 11:43:36 +00:00
|
|
|
if !IsEmpty(cValue) {
|
|
|
|
a[cField.Name] = cValue.Interface()
|
|
|
|
}
|
2017-09-30 21:36:05 +00:00
|
|
|
}
|
|
|
|
}
|
2017-09-16 16:02:26 +00:00
|
|
|
|
2017-09-30 21:36:05 +00:00
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *payloadWithContext) MarshalJSON() ([]byte, error) {
|
|
|
|
a := make(map[string]interface{})
|
2017-10-02 10:07:11 +00:00
|
|
|
if p.Context != nil {
|
|
|
|
a["@context"] = p.Context.Ref()
|
|
|
|
}
|
2017-09-30 21:36:05 +00:00
|
|
|
|
|
|
|
for k, v := range getMap(*p.Obj) {
|
2017-09-16 16:02:26 +00:00
|
|
|
a[k] = v
|
|
|
|
}
|
2017-09-30 21:36:05 +00:00
|
|
|
|
2017-09-16 16:02:26 +00:00
|
|
|
return json.Marshal(a)
|
|
|
|
}
|
|
|
|
|
2017-09-30 21:36:05 +00:00
|
|
|
func (p *payloadWithContext) UnmarshalJSON() {}
|
2017-09-16 16:02:26 +00:00
|
|
|
|
|
|
|
type Encoder struct{}
|
|
|
|
|
|
|
|
func Marshal(v interface{}, c *Context) ([]byte, error) {
|
2017-10-02 10:07:11 +00:00
|
|
|
p := payloadWithContext{c, &v}
|
2017-10-01 11:43:36 +00:00
|
|
|
return p.MarshalJSON()
|
2017-09-16 16:02:26 +00:00
|
|
|
}
|