func (p Props) MarshalJSON() ([]byte, error) {
	nk := len(p)
	b := make([]byte, 0, nk*100+20)
	if nk == 0 {
		b = append(b, []byte("null")...)
		return b, nil
	}
	b = append(b, []byte("{")...)
	cnt := 0
	var err error
	for key, val := range p {
		vt := kit.NonPtrType(reflect.TypeOf(val))
		vk := vt.Kind()
		if vk == reflect.Struct {
			knm := kit.Types.TypeName(vt)
			tstr := fmt.Sprintf("\"%v%v\": \"%v\",", struTypeKey, key, knm)
			b = append(b, []byte(tstr)...)
		}
		kstr := fmt.Sprintf("\"%v\": ", key)
		b = append(b, []byte(kstr)...)
		var kb []byte
		kb, err = json.Marshal(val)
		if err != nil {
			log.Printf("error doing json.Marshall from val: %v\n%v\n", val, err)
			log.Printf("output to point of error: %v\n", string(b))
		} else {
			if vk >= reflect.Int && vk <= reflect.Uint64 && kit.Enums.TypeRegistered(vt) {
				knm := kit.Types.TypeName(vt)
				kb, _ = json.Marshal(val)
				estr := fmt.Sprintf("\"%v(%v)%v\"", enumTypeKey, knm, string(bytes.Trim(kb, "\"")))
				b = append(b, []byte(estr)...)
			} else {
				b = append(b, kb...)
			}
		}
		if cnt < nk-1 {
			b = append(b, []byte(",")...)
		}
		cnt++
	}
	b = append(b, []byte("}")...)
	return b, nil
}
MarshalJSON saves the type information for each struct used in props, as a
separate key with the __type: prefix -- this allows the Unmarshal to
create actual types
package ki
import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"reflect"
	"strings"
	"github.com/goki/ki/kit"
)
type Props map[string]interface{}
var KiT_Props = kit.Types.AddType(&Props{}, PropsProps)
var PropsProps = Props{
	"basic-type": true,  
}
func (pr *Props) Set(key string, val interface{}) {
	if *pr == nil {
		*pr = make(Props)
	}
	(*pr)[key] = val
}
func (pr Props) Prop(key string) interface{} {
	return pr[key]
}
func (pr Props) Delete(key string) {
	delete(pr, key)
}
func SubProps(pr map[string]interface{}, key string) (Props, bool) {
	sp, ok := pr[key]
	if !ok {
		return nil, false
	}
	spp, ok := sp.(Props)
	if ok {
		return spp, true
	}
	return nil, false
}
func SubTypeProps(pr map[string]interface{}, key string) (Props, bool) {
	sp, ok := kit.TypeProp(pr, key)
	if !ok {
		return nil, false
	}
	spp, ok := sp.(Props)
	if ok {
		return spp, true
	}
	return nil, false
}
func SetPropStr(pr Props, key, val string) {
	pr[key] = val
}
func SetSubProps(pr Props, key string, sp Props) {
	pr[key] = sp
}
var struTypeKey = "__type:"
var enumTypeKey = "__enum:"
type BlankProp struct{}
type PropStruct struct {
	Name  string
	Value interface{}
}
type PropSlice []PropStruct
func (ps *PropSlice) ElemLabel(idx int) string {
	return (*ps)[idx].Name
}
func SliceProps(pr map[string]interface{}, key string) (PropSlice, bool) {
	sp, ok := pr[key]
	if !ok {
		return nil, false
	}
	spp, ok := sp.(PropSlice)
	if ok {
		return spp, true
	}
	return nil, false
}
func SliceTypeProps(pr map[string]interface{}, key string) (PropSlice, bool) {
	sp, ok := kit.TypeProp(pr, key)
	if !ok {
		return nil, false
	}
	spp, ok := sp.(PropSlice)
	if ok {
		return spp, true
	}
	return nil, false
}
func CopyProps(dest *map[string]interface{}, src map[string]interface{}, deepCopy bool) {
	if *dest == nil {
		*dest = make(Props, len(src))
	}
	for key, val := range src {
		if deepCopy {
			if pv, ok := val.(map[string]interface{}); ok {
				var nval Props
				nval.CopyFrom(pv, deepCopy)
				(*dest)[key] = nval
				continue
			} else if pv, ok := val.(Props); ok {
				var nval Props
				nval.CopyFrom(pv, deepCopy)
				(*dest)[key] = nval
				continue
			} else if pv, ok := val.(PropSlice); ok {
				var nval PropSlice
				nval.CopyFrom(pv, deepCopy)
				(*dest)[key] = nval
				continue
			}
		}
		(*dest)[key] = val
	}
}
func (dest *Props) CopyFrom(src map[string]interface{}, deepCopy bool) {
	CopyProps((*map[string]interface{})(dest), src, deepCopy)
}
func (dest *PropSlice) CopyFrom(src PropSlice, deepCopy bool) {
	if *dest == nil {
		*dest = make(PropSlice, len(src))
	}
	for i, val := range src {
		if deepCopy {
			if pv, ok := val.Value.(map[string]interface{}); ok {
				var nval Props
				CopyProps((*map[string]interface{})(&nval), pv, deepCopy)
				(*dest)[i] = PropStruct{Name: val.Name, Value: nval}
				continue
			} else if pv, ok := val.Value.(Props); ok {
				var nval Props
				CopyProps((*map[string]interface{})(&nval), pv, deepCopy)
				(*dest)[i] = PropStruct{Name: val.Name, Value: nval}
				continue
			} else if pv, ok := val.Value.(PropSlice); ok {
				var nval PropSlice
				nval.CopyFrom(pv, deepCopy)
				(*dest)[i] = PropStruct{Name: val.Name, Value: nval}
				continue
			}
		}
		(*dest)[i] = src[i]
	}
}