func ToJson(_struct interface{}) (map[string]interface{}, error) { var ( v reflect.Value t reflect.Type ) result := make(map[string]interface{}) if reflect.TypeOf(_struct).Kind() == reflect.Ptr { v = reflect.ValueOf(_struct).Elem() t = reflect.TypeOf(_struct).Elem() } else { v = reflect.ValueOf(_struct) t = reflect.TypeOf(_struct) } if t.Kind() != reflect.Struct { panic(errors.New("excepted a pointer of struct or a struct")) } for i := 0; i < v.NumField(); i++ { //fieldName := strings.ToLower(t.Field(i).Name) fieldName := t.Field(i).Name result[fieldName] = v.Field(i).Interface() } val, _ := json.MarshalIndent(result, "", "\t") fmt.Printf("%v\n", (string)(val)) return result, nil }
func MakeTypeInfo(rt reflect.Type) *TypeInfo { info := &TypeInfo{Type: rt} // If struct, register field name options if rt.Kind() == reflect.Struct { numFields := rt.NumField() structFields := []StructFieldInfo{} for i := 0; i < numFields; i++ { field := rt.Field(i) if field.PkgPath != "" { continue } skip, opts := getOptionsFromField(field) if skip { continue } structFields = append(structFields, StructFieldInfo{ Index: i, Type: field.Type, Options: opts, }) } info.Fields = structFields } return info }
func validateListType(target reflect.Type) error { // exceptions if listTypeExceptions.Has(target.Name()) { return nil } hasListSuffix := strings.HasSuffix(target.Name(), "List") hasMetadata := false hasItems := false for i := 0; i < target.NumField(); i++ { field := target.Field(i) tag := field.Tag.Get("json") switch { case strings.HasPrefix(tag, "metadata"): hasMetadata = true case tag == "items": hasItems = true if field.Type.Kind() != reflect.Slice { return fmt.Errorf("Expected items to be slice, got %s", field.Type.Kind()) } } } if hasListSuffix && !hasMetadata { return fmt.Errorf("Expected type %s to contain \"metadata\"", target.Name()) } if hasListSuffix && !hasItems { return fmt.Errorf("Expected type %s to contain \"items\"", target.Name()) } // if a type contains field Items with JSON tag "items", its name should end with List. if !hasListSuffix && hasItems { return fmt.Errorf("Type %s has Items, its name is expected to end with \"List\"", target.Name()) } return nil }
func getTableColumns(thing interface{}, typ reflect.Type) []*columnMap { columns := make([]*columnMap, 0, typ.NumField()) for i := 0; i < typ.NumField(); i++ { field := typ.Field(i) tag := strings.Split(field.Tag.Get("db"), ",") if len(tag) > 0 && tag[0] != "" { col := &columnMap{Field: i} for _, flag := range tag { switch flag { case "pk": col.PrimaryKey = true case "serialize": col.Serialize = true default: if col.Name == "" { col.Name = flag } } } columns = append(columns, col) } } return columns }
func (c *structCache) Indexes(typ reflect.Type) map[string][]int { c.l.RLock() indxs, ok := c.m[typ] c.l.RUnlock() if ok { return indxs } numField := typ.NumField() indxs = make(map[string][]int, numField) for i := 0; i < numField; i++ { f := typ.Field(i) if f.PkgPath != "" { continue } tokens := strings.Split(f.Tag.Get("pg"), ",") name := tokens[0] if name == "-" { continue } if name == "" { name = formatColumnName(f.Name) } indxs[name] = f.Index } c.l.Lock() c.m[typ] = indxs c.l.Unlock() return indxs }
func getFields(typ reflect.Type) *fields { numField := typ.NumField() fs := newFields(numField) for i := 0; i < numField; i++ { f := typ.Field(i) if f.PkgPath != "" && !f.Anonymous { continue } name, opts := parseTag(f.Tag.Get("msgpack")) if name == "-" { continue } if opts.Contains("inline") { inlineFields(fs, f) continue } if name == "" { name = f.Name } field := field{ name: name, index: f.Index, omitEmpty: opts.Contains("omitempty"), encoder: getEncoder(f.Type), decoder: getDecoder(f.Type), } fs.Add(&field) } return fs }
func (db *DB) rawSelectByStruct(structType reflect.Type, qi SqlQueryInfo) (rows *sql.Rows, fields []string, err error) { // nums of struct's fields lf := structType.NumField() // type's fields fields = make([]string, 0, lf) // sql select columns, it's Snake Cased columns := make([]string, 0, lf) // get fields in structType, // and convert to sql query column name for i := 0; i < lf; i++ { structField := structType.Field(i) fieldName := structField.Name fields = append(fields, fieldName) columns = append(columns, utils.SnakeCasedName(fieldName)) } // tableName := utils.SnakeCasedName(utils.StructName(s)) tableName := utils.SnakeCasedName(structType.Name()) // TODO: check the fileds has specified ? qi.Fields = strings.Join(columns, ", ") // run query from db rows, err = db.Select(tableName, qi) return }
// visit calls the visitor function for each string it finds, and will descend // recursively into structures and slices. If any visitor returns an error then // the search will stop and that error will be returned. func visit(path string, v reflect.Value, t reflect.Type, fn visitor) error { switch v.Kind() { case reflect.String: return fn(path, v) case reflect.Struct: for i := 0; i < v.NumField(); i++ { vf := v.Field(i) tf := t.Field(i) newPath := fmt.Sprintf("%s.%s", path, tf.Name) if err := visit(newPath, vf, tf.Type, fn); err != nil { return err } } case reflect.Slice: for i := 0; i < v.Len(); i++ { vi := v.Index(i) ti := vi.Type() newPath := fmt.Sprintf("%s[%d]", path, i) if err := visit(newPath, vi, ti, fn); err != nil { return err } } } return nil }
func getFieldInfos(rType reflect.Type, parentIndexChain []int) []fieldInfo { fieldsCount := rType.NumField() fieldsList := make([]fieldInfo, 0, fieldsCount) for i := 0; i < fieldsCount; i++ { field := rType.Field(i) if field.PkgPath != "" { continue } indexChain := append(parentIndexChain, i) // if the field is an embedded struct, create a fieldInfo for each of its fields if field.Anonymous && field.Type.Kind() == reflect.Struct { fieldsList = append(fieldsList, getFieldInfos(field.Type, indexChain)...) continue } fieldInfo := fieldInfo{IndexChain: indexChain} fieldTag := field.Tag.Get("csv") fieldTags := strings.Split(fieldTag, TagSeparator) filteredTags := []string{} for _, fieldTagEntry := range fieldTags { if fieldTagEntry != "omitempty" { filteredTags = append(filteredTags, fieldTagEntry) } } if len(filteredTags) == 1 && filteredTags[0] == "-" { continue } else if len(filteredTags) > 0 && filteredTags[0] != "" { fieldInfo.keys = filteredTags } else { fieldInfo.keys = []string{field.Name} } fieldsList = append(fieldsList, fieldInfo) } return fieldsList }
func (p *property) readFromStruct(t reflect.Type) { p.Type = "object" p.Properties = make(map[string]*property, 0) p.AdditionalProperties = false count := t.NumField() for i := 0; i < count; i++ { field := t.Field(i) tag := field.Tag.Get("json") name, opts := parseTag(tag) if name == "" { name = field.Name } p.Properties[name] = &property{} p.Properties[name].read(field.Type, opts) comment, ok := commentMap[field.Name] if ok { p.Properties[name].Description = comment } if !opts.Contains("omitempty") { p.Required = append(p.Required, name) } } }
// Create a fieldmap for a given type and return its fieldmap (or error) func getFieldmap(t reflect.Type) (fm fieldmap, err error) { // if we have a fieldmap cached, return it t, err = BaseStructType(t) if err != nil { return nil, err } fm, ok := fieldmapCache[t] if ok { return fm, nil } else { fm = fieldmap{} } var f reflect.StructField var name string for i := 0; i < t.NumField(); i++ { f = t.Field(i) name = strings.ToLower(f.Name) if tag := f.Tag.Get("db"); tag != "" { name = tag } fm[name] = i } fieldmapCache[t] = fm return fm, nil }
// yamlTags returns a map from yaml tag to the field index for the string fields in the given type. func yamlTags(t reflect.Type) map[string]int { if t.Kind() != reflect.Struct { panic(errors.Errorf("cannot get yaml tags on type %s", t)) } tags := make(map[string]int) for i := 0; i < t.NumField(); i++ { f := t.Field(i) if f.Type != reflect.TypeOf("") { continue } if tag := f.Tag.Get("yaml"); tag != "" { if i := strings.Index(tag, ","); i >= 0 { tag = tag[0:i] } if tag == "-" { continue } if tag != "" { f.Name = tag } } tags[f.Name] = i } return tags }
func serialiseStruct(out io.Writer, v reflect.Value, t reflect.Type, context string, level uint, entities map[uint32][]byte) { for i := 0; i < t.NumField(); i++ { f := t.Field(i) if f.Name == "XXX_unrecognized" { continue } fv := v.Field(i) switch f.Type.Kind() { case reflect.Slice: if f.Type.Elem().Kind() == reflect.Uint8 { serialiseValue(out, f.Name, fv, f.Type, context, level, entities) } else { if f.Type.Elem().Kind() == reflect.Ptr { for i := 0; i < fv.Len(); i++ { serialiseValue(out, f.Name, fv.Index(i).Elem(), f.Type.Elem().Elem(), context, level, entities) } } else { for i := 0; i < fv.Len(); i++ { serialiseValue(out, f.Name, fv.Index(i), f.Type.Elem(), context, level, entities) } } } case reflect.Ptr: if !fv.IsNil() { serialiseValue(out, f.Name, fv.Elem(), f.Type.Elem(), context, level, entities) } default: panic(fmt.Sprintf("Don't know how to serialize %s", f)) } } }
func QueryBuilder(clause, tablename, input string, TableModel interface{}) (retVal string) { clause = strings.ToUpper(clause) retVal = "" if clause == "INSERT" { retVal += clause + " INTO " + tablename + " VALUES (" } else if clause == "ADD COLUMN" { retVal += "ALTER TABLE" + tablename + " ADD COLUMNS (" } else if clause == "SELECT" { retVal += "SELECT * FROM " + tablename + ";" } var v reflect.Type v = reflect.TypeOf(TableModel).Elem() if v.Kind() == reflect.Struct { for i := 0; i < v.NumField(); i++ { if clause == "INSERT" { retVal += input + ");" break } else if clause == "ADD COLUMN" { retVal += reflect.ValueOf(TableModel).Elem().Field(i).String() + " " + v.Field(i).Type.String() } if i < v.NumField()-1 { retVal += "," } else { retVal += ");" } } } return retVal }
func addFields(m *Model, t reflect.Type, v reflect.Value) { for i := 0; i < t.NumField(); i++ { field := t.Field(i) sqlTag := field.Tag.Get("sql") if sqlTag == "-" { continue } if field.Anonymous && field.Type.Kind() == reflect.Struct { addFields(m, field.Type, v.Field(i)) continue } parsedSqlTags := parseTags(sqlTag) rawValidateTag := field.Tag.Get("validate") parsedValidateTags := make(map[string]string) if len(rawValidateTag) > 0 { if rawValidateTag[:1] == "^" { parsedValidateTags["regexp"] = rawValidateTag } else { parsedValidateTags = parseTags(rawValidateTag) } } fd := &ModelField{ Name: toSnake(field.Name), Value: v.FieldByName(field.Name).Interface(), SqlTags: parsedSqlTags, ValidateTags: parsedValidateTags, RawTag: field.Tag, } if fd.PrimaryKey() { m.Pk = fd } m.Fields = append(m.Fields, fd) } }
func (d decoder) decodeField(sf reflect.StructField, t reflect.Type, v reflect.Value) MessageRejectError { if sf.Tag.Get("fix") != "" { fixTag, err := strconv.Atoi(sf.Tag.Get("fix")) if err != nil { panic(err) } if !d.FieldMap.Has(Tag(fixTag)) { return nil } return d.decodeValue(Tag(fixTag), t, v) } switch t.Kind() { case reflect.Ptr: v.Set(reflect.New(t.Elem())) return d.decodeField(sf, t.Elem(), v.Elem()) case reflect.Struct: for i := 0; i < t.NumField(); i++ { if err := d.decodeField(t.Field(i), t.Field(i).Type, v.Field(i)); err != nil { return err } } } return nil }
func getParams(elem reflect.Type) []Parameter { parameters := []Parameter{} l := elem.NumField() for i := 0; i < l; i++ { f := elem.Field(i) jsonName := f.Tag.Get("json") if f.Anonymous { parameters = append(parameters, getParams(f.Type)...) } else if jsonName != "" { p := Parameter{} p.Name = jsonName p.Type = f.Type.String() p.Description = f.Tag.Get("description") enum := f.Tag.Get("enum") if enum != "" { p.EnumValues = strings.Split(enum, ",") p.Type = "enum" } else { p.EnumValues = []string{} } parameters = append(parameters, p) } } return parameters }
func checkStructs(c *C, t reflect.Type, structsChecked map[string]struct{}) { for t.Kind() == reflect.Ptr || t.Kind() == reflect.Map || t.Kind() == reflect.Slice { t = t.Elem() } if t.Kind() != reflect.Struct { return } if _, present := structsChecked[t.String()]; present { // Already checked this type return } structsChecked[t.String()] = struct{}{} byUpperCase := make(map[string]int) for i := 0; i < t.NumField(); i++ { sf := t.Field(i) // Check that the yaml tag does not contain an _. yamlTag := sf.Tag.Get("yaml") if strings.Contains(yamlTag, "_") { c.Fatalf("yaml field name includes _ character: %s", yamlTag) } upper := strings.ToUpper(sf.Name) if _, present := byUpperCase[upper]; present { c.Fatalf("field name collision in configuration object: %s", sf.Name) } byUpperCase[upper] = i checkStructs(c, sf.Type, structsChecked) } }
// create new schema with type func NewSchema(rt reflect.Type, size int) (sc *Schema, e error) { numField := rt.NumField() if numField < 1 { e = fmtError(ErrStrStructNeedField, rt) return } sc = new(Schema) sc.Name = rt.Name() sc.Max = 0 sc.Index = []string{} sc.ChunkSize = size // parse fields for i := 0; i < numField; i++ { field := rt.Field(i) tag := field.Tag.Get("jx") if tag == "" || tag == "-" { continue } if tag == "pk" { if field.Type.Kind() != reflect.Int { e = fmtError(ErrStrStructPkNeedInt, rt, field.Name) return } sc.PK = field.Name continue } if tag == "index" { sc.Index = append(sc.Index, field.Name) } } return }
func getFields(t reflect.Type) []reflect.StructField { fields := make([]reflect.StructField, 0) if t.Kind() == reflect.Ptr { t = t.Elem() } for i := 0; i < t.NumField(); i++ { f := t.Field(i) ft := f.Type if ft.Kind() == reflect.Ptr { ft = ft.Elem() } switch ft.Kind() { case reflect.Struct: if f.Anonymous { fields = append(fields, getFields(ft)...) } else if len(f.PkgPath) == 0 { fields = append(fields, f) } default: if len(f.PkgPath) == 0 { fields = append(fields, f) } } } return fields }
func readStructColumns(t reflect.Type) (cols []*ColumnMap, version *ColumnMap) { n := t.NumField() for i := 0; i < n; i++ { f := t.Field(i) if f.Anonymous && f.Type.Kind() == reflect.Struct { // Recursively add nested fields in embedded structs. subcols, subversion := readStructColumns(f.Type) cols = append(cols, subcols...) if subversion != nil { version = subversion } } else { columnName := f.Tag.Get("db") if columnName == "" { columnName = f.Name } cm := &ColumnMap{ ColumnName: columnName, Transient: columnName == "-", fieldName: f.Name, gotype: f.Type, } cols = append(cols, cm) if cm.fieldName == "Version" { version = cm } } } return }
func newStructInspection(t reflect.Type) (*structInspection, error) { si := &structInspection{ rtype: t, orderedFields: make([]*field, 0), goFields: make(map[string]*field, 0), cassandraFields: make(map[string]*field, 0), globalTags: make(map[string]string), } n := t.NumField() for i := 0; i < n; i++ { sf := t.Field(i) for _, t := range recognizedGlobalTags { if v := sf.Tag.Get(t); v != "" { si.globalTags[t] = v } } f, err := newField(i, sf) if err != nil { return nil, errors.New(fmt.Sprint("Error in struct ", t.Name(), ": ", err)) } if f != nil { si.orderedFields = append(si.orderedFields, f) si.goFields[f.name] = f si.cassandraFields[f.cassandraName] = f } } return si, nil }
func sizeof(t reflect.Type) (int, error) { switch t.Kind() { case reflect.Array: n, err := sizeof(t.Elem()) if err != nil { return 0, err } return t.Len() * n, nil case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s, err := sizeof(t.Field(i).Type) if err != nil { return 0, err } sum += s } return sum, nil case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: return int(t.Size()), nil } return 0, errors.New("invalid type " + t.String()) }
func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) { for i := 0; i < st.NumField(); i++ { field := sv.Field(i) tag, omitempty := jsonTag(st.Field(i)) if len(tag) == 0 { continue } ft := field.Type() kind := ft.Kind() if isPointerKind(kind) { kind = ft.Elem().Kind() if !field.IsNil() { field = reflect.Indirect(field) } } switch { case isValueKind(kind): addParam(result, tag, omitempty, field) case kind == reflect.Array || kind == reflect.Slice: if isValueKind(ft.Elem().Kind()) { addListOfParams(result, tag, omitempty, field) } case isStructKind(kind) && !(zeroValue(field) && omitempty): convertStruct(result, ft, field) } } }
func getOrCreateSchema(definitions Definitions, t reflect.Type) *Schema { var result Schema if t.Kind() == reflect.Ptr { t = t.Elem() } if t.Kind() == reflect.Map { if t.Key().Kind() != reflect.String { panic("swagger supports only maps with string keys") } result.Type = "object" result.AdditionalProperties = getOrCreateSchema(definitions, t.Elem()) return &result } if t.Kind() == reflect.Interface { result.Type = "object" return &result } result.Type = typeName(t) if result.Type == "object" { name := t.String() if _, ok := definitions[name]; ok { result = Schema{Ref: "#/definitions/" + name} return &result } definitions[name] = result if t.NumField() > 0 { result.Properties = Properties{} } for i := 0; i < t.NumField(); i++ { field := t.Field(i) if field.PkgPath != "" { continue } name := field.Tag.Get("json") if name == "" { name = field.Tag.Get("key") if name == "" { name = field.Name } } if field.Type.Kind() != reflect.Ptr { result.Required = append(result.Required, name) } fieldSchema := getOrCreateSchema(definitions, field.Type) fieldSchema.Description = field.Tag.Get("description") result.Properties[name] = fieldSchema } definitions[name] = result result = Schema{Ref: "#/definitions/" + name} } else if result.Type == "array" { itemsSchema := getOrCreateSchema(definitions, t.Elem()) result.Items = &Items{*itemsSchema} } return &result }
func populateFormStruct(formStruct reflect.Value, typ reflect.Type, req *http.Request, errors *Errors) { for i := 0; i < typ.NumField(); i++ { typeField := typ.Field(i) if typeField.Type.Kind() == reflect.Struct { populateFormStruct(formStruct.Field(i), typeField.Type, req, errors) } else if inputFieldName := typeField.Tag.Get("form"); inputFieldName != "" { structField := formStruct.Field(i) if !structField.CanSet() { continue } inputValue, exists := req.Form[inputFieldName] if !exists { continue } numElems := len(inputValue) if structField.Kind() == reflect.Slice && numElems > 0 { sliceOf := structField.Type().Elem().Kind() slice := reflect.MakeSlice(structField.Type(), numElems, numElems) for i := 0; i < numElems; i++ { setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors) } formStruct.Field(i).Set(slice) } else { setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors) } } } }
// hasUnrecognizedKeys finds unrecognized keys and warns about them on stderr. // returns false when no unrecognized keys were found, true otherwise. func hasUnrecognizedKeys(inCfg interface{}, refType reflect.Type) (warnings bool) { if refType.Kind() == reflect.Ptr { refType = refType.Elem() } switch inCfg.(type) { case map[interface{}]interface{}: ks := inCfg.(map[interface{}]interface{}) keys: for key := range ks { for i := 0; i < refType.NumField(); i++ { sf := refType.Field(i) tv := sf.Tag.Get("yaml") if tv == key { if warn := hasUnrecognizedKeys(ks[key], sf.Type); warn { warnings = true } continue keys } } glog.Errorf("Unrecognized keyword: %v", key) warnings = true } case []interface{}: ks := inCfg.([]interface{}) for i := range ks { if warn := hasUnrecognizedKeys(ks[i], refType.Elem()); warn { warnings = true } } default: } return }
func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) { for i := 0; i < tpe.NumField(); i++ { targetDes := tpe.Field(i) if targetDes.PkgPath != "" { // unexported continue } if targetDes.Anonymous { // walk embedded structures tree down first buildnameIndex(targetDes.Type, idx, reverseIdx) continue } if tag := targetDes.Tag.Get("json"); tag != "" { parts := strings.Split(tag, ",") if len(parts) == 0 { continue } nm := parts[0] if nm == "-" { continue } if nm == "" { // empty string means we want to use the Go name nm = targetDes.Name } idx[nm] = targetDes.Name reverseIdx[targetDes.Name] = nm } } }
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. func sizeof(t reflect.Type) int { switch t.Kind() { case reflect.Array: if s := sizeof(t.Elem()); s >= 0 { return s * t.Len() } case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { s := sizeof(t.Field(i).Type) if s < 0 { return -1 } sum += s } return sum case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr: return int(t.Size()) } return -1 }
// MakeMeta gets meta for given type. func MakeMeta(t reflect.Type) Meta { if t.Kind() == reflect.Ptr { t = t.Elem() } if t.Kind() == reflect.Slice { t = t.Elem() } var m = Meta{ SetID: NoopSetter, SetCreatedAt: NoopSetter, SetUpdatedAt: NoopSetter, } for i := 0; i < t.NumField(); i++ { var f = t.Field(i) if strings.ToLower(f.Name) == "id" { m.GetID = MakeGetter(f) m.SetID = MakeSetter(f) continue } if f.Name == "CreatedAt" { m.SetCreatedAt = MakeSetter(f) continue } if f.Name == "UpdatedAt" { m.SetUpdatedAt = MakeSetter(f) continue } } return m }