// convertResult convert reflect.Value to http result func convertResult(ctx *HttpContext, v reflect.Value) HttpResult { i := v.Interface() if r, ok := i.(HttpResult); ok { return r } if Formatters != nil { for _, f := range Formatters { if formatted, ok := f(ctx, v.Interface()); ok { return formatted } } } kind := reflect.Indirect(v).Kind() switch { case gotype.IsSimple(kind): return &DataResult{Data: i} case gotype.IsStruct(kind) || gotype.IsCollect(kind): accept := ctx.Accept() switch { case strings.Index(accept, "xml") > -1: return &XmlResult{Data: v.Interface()} case strings.Index(accept, "jsonp") > -1: return &JsonpResult{Data: v.Interface()} default: return &JsonResult{Data: v.Interface()} } } return &ContentResult{Data: i} }
func (n *Node) setMap(v reflect.Value) { // fmt.Println("setmap", nameOfNodeType(n.Type), v.Type(), v.Kind()) // fmt.Println(n.Dump()) kind := v.Kind() if n.Type != NodeHash || kind != reflect.Map { return } typ := v.Type() if n.Hash == nil { if v.CanSet() { v.Set(reflect.Zero(typ)) } return } if typ.Key() != gotype.TypeString { // only support string key return } if v.IsNil() { if v.CanSet() { v.Set(reflect.MakeMap(typ)) } else { return } } elemType := typ.Elem() elemKind := elemType.Kind() simple := gotype.IsSimple(elemKind) for name, x := range n.Hash { if simple && x.Type == NodeLiteral { mapElem, err := gotype.Atok(x.Literal, elemKind) if err == nil { v.SetMapIndex(reflect.ValueOf(name), mapElem) } } else { var mapElem reflect.Value if elemType.Kind() == reflect.Ptr { mapElem = reflect.New(elemType.Elem()) } else { mapElem = reflect.New(elemType) } x.set(mapElem) v.SetMapIndex(reflect.ValueOf(name), mapElem) } } }
// Bind func (binder *structBinder) Bind(ctx *HttpContext) ([]reflect.Value, error) { numIn := binder.method.NumIn args := make([]reflect.Value, numIn, numIn) for i := 0; i < numIn; i++ { in := binder.method.In[i] args[i] = reflect.Zero(in) if in.Kind() == reflect.Struct { args[i] = reflect.New(in).Elem() } else if in.Kind() == reflect.Ptr && in.Elem().Kind() == reflect.Struct { args[i] = reflect.New(in.Elem()) } else { continue } uType := gotype.UnderlyingType(in) uValue := gotype.Underlying(args[i]) filedNum := uType.NumField() for f := 0; f < filedNum; f++ { field := uType.Field(f) fieldValue := uValue.Field(f) fieldType := field.Type if !fieldValue.CanSet() { continue } fieldKind := fieldType.Kind() name := strings.ToLower(field.Name) str, ok := ctx.RouteData[name] if !ok { str = ctx.Request.FormValue(name) } if str == "" { continue } if gotype.IsSimple(fieldKind) { gotype.Value(fieldValue).Parse(str) } else { //TODO } } } return args, nil }
func (n *Node) setArray(v reflect.Value) { kind := v.Kind() if n.Type != NodeList || (kind != reflect.Slice && kind != reflect.Array) { return } typ := v.Type() if n.List == nil { if v.CanSet() { v.Set(reflect.Zero(typ)) } return } l := len(n.List) if kind == reflect.Slice { if v.CanSet() { v.Set(reflect.MakeSlice(v.Type(), l, l)) } else { return } } vl := v.Len() elemType := typ.Elem() elemKind := elemType.Kind() simple := gotype.IsSimple(elemKind) for i, x := range n.List { if i < vl { // capacity of array maybe less of i if simple && x.Type == NodeLiteral { gotype.Value(v.Index(i)).Parse(x.Literal) } else { x.set(v.Index(i)) } } } if kind == reflect.Array && l < vl { for i := l; i < vl; i++ { z := reflect.Zero(v.Type().Elem()) //reset v.Index(i).Set(z) } } }
func (n *Node) setObject(v reflect.Value) { kind := v.Kind() if n.Type != NodeHash || kind != reflect.Struct { return } typ := v.Type() if n.Hash == nil { if v.CanSet() { v.Set(reflect.Zero(typ)) return } } numFiled := typ.NumField() for i := 0; i < numFiled; i++ { field := typ.Field(i) if field.PkgPath != "" { continue } name := field.Name filedNode, ok := n.Child(name) if !ok { filedNode, ok = n.ChildFold(name) } if !ok { continue } fv := v.Field(i) if !fv.CanSet() { continue } kind := field.Type.Kind() if filedNode.Type == NodeLiteral && gotype.IsSimple(kind) { gotype.Value(fv).Parse(filedNode.Literal) } else { filedNode.set(fv) } } }
func (n *Node) set(v reflect.Value) { // if !v.CanSet() || !v.IsValid() { // return // } // fmt.Println("set==", nameOfNodeType(n.Type), v.Type(), v.Kind()) // fmt.Println(n.Dump()) kind := v.Kind() switch { case gotype.IsSimple(kind): if n.Literal != "" { gotype.Value(v).Parse(n.Literal) } case kind == reflect.Invalid || kind == reflect.Uintptr || kind == reflect.UnsafePointer || kind == reflect.Func || kind == reflect.Chan || kind == reflect.Complex64 || kind == reflect.Complex128: //TODO: unsupport case kind == reflect.Array: n.setArray(v) case kind == reflect.Slice: n.setArray(v) case kind == reflect.Map: n.setMap(v) case kind == reflect.Struct: n.setObject(v) case kind == reflect.Interface: if n.Type == NodeLiteral { gotype.Value(v).Parse(n.Literal) } case kind == reflect.Ptr: if v.IsNil() && v.CanSet() { v.Set(reflect.New(v.Type().Elem())) } n.set(v.Elem()) default: //TODO: } }
// TODO: adjust indent algorithm func (e *encoder) visitReflectValue(v reflect.Value) { if !v.IsValid() { e.WriteString("") } //v = gotype.Underlying(v) kind := v.Kind() switch kind { case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: e.WriteString(gotype.Value(v).Format()) case reflect.String: s := v.String() if b, quote := stringNeedQuote(s); b { e.WriteString(quote) e.WriteString(s) e.WriteString(quote) //e.WriteString("\n") } else { e.WriteString(s) } case reflect.Struct: //fmt.Fprintln(e, "{") e.WriteByte('{') e.WriteByte('\n') e.indentInner() typ := v.Type() count := typ.NumField() for i := 0; i < count; i++ { f := typ.Field(i) if f.PkgPath != "" { continue } e.indent() //fmt.Fprint(e, f.Name) e.WriteString(f.Name) //fmt.Fprint(e, ":") e.WriteByte(':') e.visitReflectValue(v.Field(i)) //fmt.Fprintln(e, "") e.WriteByte('\n') } e.indentOuter() e.indent() //fmt.Fprintln(e, "}") e.WriteByte('}') e.WriteByte('\n') case reflect.Map: if !gotype.IsSimple(v.Type().Key().Kind()) { return } if v.IsNil() { //fmt.Fprint(e, "") //fmt.Fprint(e, "null") e.WriteByte(' ') break } //fmt.Fprintln(e, "{") e.WriteByte('{') e.WriteByte('\n') e.indentInner() keys := v.MapKeys() for _, k := range keys { e.indent() //fmt.Fprint(e, k) e.WriteString(k.String()) //fmt.Fprint(e, ":") e.WriteByte(':') e.visitReflectValue(v.MapIndex(k)) //fmt.Fprintln(e, "") e.WriteByte('\n') } e.indentOuter() e.indent() //fmt.Fprintln(e, "}") e.WriteByte('}') e.WriteByte('\n') case reflect.Slice: if v.IsNil() { //fmt.Fprint(e, "") //fmt.Fprint(e, "null") e.WriteByte(' ') break } e.visitArray(v) case reflect.Array: e.visitArray(v) case reflect.Interface, reflect.Ptr: if v.IsNil() || !v.IsValid() { //fmt.Fprint(e, "") //fmt.Fprint(e, "null") e.WriteByte(' ') return } e.visitReflectValue(v.Elem()) default: fmt.Fprint(e, v.Interface()) //return errors.New("Unsupported type " + v.Type().String()) } return }