各种结构相互转换

map转结构体的函数

封装的函数

// 实现map转结构体的函数
func Map2Struct(source map[string]interface{}, target interface{}) {
    if err := mapstructure.Decode(source, target); err != nil {
    }
    Map2StructTaged(source, target, "json")
}
func Map2StructTaged(source map[string]interface{}, target interface{}, tag string) {
    cfg := &mapstructure.DecoderConfig{
        Metadata: nil,
        Result:   target,
        TagName:  tag,
    }
    decoder, _ := mapstructure.NewDecoder(cfg)
    if err := decoder.Decode(source); err != nil {
    }
}

使用原生方法进行的测试

package main

import (
    "fmt"
    "github.com/goinggo/mapstructure"
)

type Person struct {
    Name string
    Age int
}

func MapToStruct() (p Person){
    mapInstance := make(map[string]interface{})
    mapInstance["Name"] = "liang637210"
    mapInstance["Age"] = 28

    var person Person
    //将 map 转换为指定的结构体
    if err := mapstructure.Decode(mapInstance, &person); err != nil {
        fmt.Println(err)
    }
    fmt.Printf("map2struct后得到的 struct 内容为:%v,类型为:%T \n", person,person)
    return person
}

func main(){
    ret := MapToStruct()

    fmt.Printf("ret>>> %v, %T",ret, ret)

}

其他

package parsexx

import (
    "database/sql"
    "encoding/json"
    "errors"
    "fmt"
    "log"
    "reflect"
    "strings"
    "10.0.2.35/bicloud/optimus/src/utils/mathtool"
    "github.com/chenhg5/collection"
    "github.com/goinggo/mapstructure"
)

// Json2Any 字符串转一切,需传入指针
func Json2Any(infoByte []byte, target interface{}) error {

    if err := json.Unmarshal(infoByte, target); err != nil {
        return errors.New(fmt.Sprintf("%v", err))
    }
    return nil
}

func Json2List(infoByte []byte, target *[]interface{}) error {

    if err := json.Unmarshal(infoByte, target); err != nil {
        return errors.New(fmt.Sprintf("%v", err))
    }
    return nil
}

func struct2Map(obj interface{}, protoAdapt bool) map[string]interface{} {
    t := reflect.TypeOf(obj)
    v := reflect.ValueOf(obj)

    var data = make(map[string]interface{})
    for i := 0; i < t.NumField(); i++ {
        // 处理proto struct:首字母小写、XXX_字段删除
        keyName := t.Field(i).Name
        if protoAdapt {
            if strings.HasPrefix(keyName, "XXX_") {
                continue
            }
            keyName = mathtool.StrFirstToLow(keyName)
        }
        data[keyName] = v.Field(i).Interface()
    }
    return data
}

func Struct2Map(source interface{}) map[string]interface{} {
    return struct2Map(source, true)
}

func Map2Struct(source map[string]interface{}, target interface{}) {
    if err := mapstructure.Decode(source, target); err != nil {
    }
    // Map2StructTaged(source, target, "json")
}

func Map2StructTaged(source map[string]interface{}, target interface{}, tag string) {
    cfg := &mapstructure.DecoderConfig{
        Metadata: nil,
        Result:   target,
        TagName:  tag,
    }
    decoder, _ := mapstructure.NewDecoder(cfg)
    if err := decoder.Decode(source); err != nil {

    }
}

func ToSqlNullHookFunc(f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) {

    switch f {
    case reflect.String:
        var s sql.NullString
        if t == reflect.Struct {
            s = sql.NullString{
                String: data.(string),
                Valid:  true,
            }
            return s, nil
        }
    case reflect.Int32:
        var s sql.NullInt32
        if t == reflect.Struct {
            s = sql.NullInt32{
                Int32: data.(int32),
                Valid: true,
            }
            return s, nil
        }
    case reflect.Int64:
        var s sql.NullInt64
        if t == reflect.Struct {
            s = sql.NullInt64{
                Int64: data.(int64),
                Valid: true,
            }
            return s, nil
        }
    default:
        return data, nil
    }

    return data, nil
}

func Map2SqlTaged(source map[string]interface{}, target interface{}, tag string) {
    cfg := &mapstructure.DecoderConfig{
        Metadata:   nil,
        DecodeHook: ToSqlNullHookFunc, // 处理sql structure
        Result:     target,
        TagName:    tag,
    }
    decoder, _ := mapstructure.NewDecoder(cfg)
    if err := decoder.Decode(source); err != nil {

    }
}

func Map2Json(source map[string]interface{}) []byte {
    target, err := json.Marshal(source)
    if err != nil {
    }
    return target
}

func Json2Map(source []byte, target *map[string]interface{}) {
    if err := json.Unmarshal([]byte(source), target); err != nil {
    }
}

func Struct2Json(source interface{}) []byte {
    target, err := json.Marshal(source)
    if err != nil {

    }
    return target
}

func Json2Struct(source []byte, target interface{}) {
    err := json.Unmarshal([]byte(source), target)
    if err != nil {

    }
}

// StructByDelField 删除某些字段后返回新的struct
func StructByDelField(obj interface{}, fields []string, target interface{}) {

    t := reflect.TypeOf(obj)
    v := reflect.ValueOf(obj)

    var data = make(map[string]interface{})
    for i := 0; i < t.NumField(); i++ {
        keyName := t.Field(i).Name
        if collection.Collect(fields).Contains(keyName) {
            continue
        }
        data[keyName] = v.Field(i).Interface()
    }
    Map2Struct(data, target)
}

// GetFieldName 获取结构体中字段的名称
func GetFieldName(structName interface{}) []string {
    // t := reflect.TypeOf(structName)
    // if t.Kind() == reflect.Ptr {
    //     t = t.Elem()
    // }
    // if t.Kind() != reflect.Struct {
    //     return nil
    // }
    // fieldNum := t.NumField()
    // result := make([]string, 0, fieldNum)
    // for i := 0; i < fieldNum; i++ {
    //     result = append(result, t.Field(i).Name)
    // }
    // return result
    return GetFieldNameTaged(structName, "")
}

// GetFieldNameTaged 获取结构体tag名字
func GetFieldNameTaged(structName interface{}, tag string) []string {
    t := reflect.TypeOf(structName)
    if t.Kind() == reflect.Ptr {
        t = t.Elem()
    }
    if t.Kind() != reflect.Struct {
        log.Println("Check type error not Struct")
        return nil
    }
    fieldNum := t.NumField()
    result := make([]string, 0, fieldNum)
    for i := 0; i < fieldNum; i++ {
        if tag != "" {
            name := t.Field(i).Tag.Get(tag)
            result = append(result, name)
        } else {
            result = append(result, t.Field(i).Name)
        }
    }
    return result
}

~~~

posted on 2020-10-28 11:50  江湖乄夜雨  阅读(407)  评论(0编辑  收藏  举报