|
|
|
@ -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
|
|
|
|
|
}
|
|
|
|
|