Support Cbor

Support Cbor
pull/179/head
Robert 3 weeks ago
parent cfe9e112aa
commit 5cb9322512

@ -3,12 +3,14 @@ package ncdomain
import "encoding/json"
import "net"
import "fmt"
import "github.com/fxamacker/cbor"
import "github.com/miekg/dns"
import "encoding/base64"
import "encoding/hex"
import "github.com/namecoin/ncdns/util"
import "strings"
import "strconv"
import "reflect"
const depthLimit = 16
const mergeDepthLimit = 4
@ -355,8 +357,15 @@ func ParseValue(name, jsonValue string, resolve ResolveFunc, errFunc ErrorFunc)
err := json.Unmarshal([]byte(jsonValue), &rv)
if err != nil {
errFunc.add(err)
return
errCBOR := cbor.Unmarshal([]byte(jsonValue), &rv)
if errCBOR != nil {
errFunc.add(err)
errFunc.add(fmt.Errorf("failed to decode cbor (after JSON decoding failed): %v", errCBOR))
return
}
// Some unmarshallers (e.g. CBOR) will create
// map[interface{}]interface{} which is incompatible
rv = makeJSONSafe(rv)
}
if resolve == nil {
@ -1083,3 +1092,60 @@ func (v *Value) moveEmptyMapItems() {
}
}
}
// makeJSONSafe walks an interface to ensure all maps use string keys so that
// encoding to JSON (or YAML) works. Some unmarshallers (e.g. CBOR) will
// create map[interface{}]interface{} which causes problems marshalling.
// See https://github.com/fxamacker/cbor/issues/206
// The function was taken from https://github.com/danielgtaylor/restish/blob/d16bdd717c3a73efbda8ba48a3af6bf8f5995b67/cli/formatter.go#L292-L338
func makeJSONSafe(obj interface{}) interface{} {
value := reflect.ValueOf(obj)
for value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Slice:
if _, ok := obj.([]byte); ok {
// Special case: byte slices get special encoding rules in various
// formats, so keep them as-is. Without this is breaks the base64
// encoding for JSON and gives you an array of integers instead.
return obj
}
returnSlice := make([]interface{}, value.Len())
for i := 0; i < value.Len(); i++ {
returnSlice[i] = makeJSONSafe(value.Index(i).Interface())
}
return returnSlice
case reflect.Map:
tmpData := make(map[string]interface{})
for _, k := range value.MapKeys() {
kStr := ""
if s, ok := k.Interface().(string); ok {
kStr = s
} else {
kStr = fmt.Sprintf("%v", k.Interface())
}
tmpData[kStr] = makeJSONSafe(value.MapIndex(k).Interface())
}
return tmpData
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return float64(value.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return float64(value.Uint())
// case reflect.Struct:
// for i := 0; i < value.NumField(); i++ {
// field := value.Field(i)
// spew.Dump(field, field.Kind(), field.CanSet())
// switch field.Kind() {
// case reflect.Slice, reflect.Map, reflect.Struct, reflect.Ptr:
// if field.CanSet() {
// field.Set(reflect.ValueOf(makeJSONSafe(field.Interface())))
// }
// }
// }
}
return obj
}

Loading…
Cancel
Save