duancan1732 2012-07-17 17:43
浏览 60
已采纳

转到-复制结构之间的所有公共字段

I have a database that stores JSON, and a server that provides an external API to whereby through an HTTP post, values in this database can be changed. The database is used by different processes internally, and as such have a common naming scheme.

The keys the customer sees are different, but map 1:1 with the keys in the database (there are unexposed keys). For example:

This is in the database:

{ "bit_size": 8, "secret_key": false }

And this is presented to the client:

{ "num_bits": 8 }

The API can change with respect to field names, but the database always has consistent keys.

I have named the fields the same in the struct, with different flags to the json encoder:

type DB struct {
    NumBits int  `json:"bit_size"`
    Secret  bool `json:"secret_key"`
}
type User struct {
    NumBits int `json:"num_bits"`
}

I'm using encoding/json to do the Marshal/Unmarshal.

Is reflect the right tool for this? Is there an easier way since all of the keys are the same? I was thinking some kind of memcpy (if I kept the user fields in the same order).

  • 写回答

7条回答 默认 最新

  • dqwh2717 2012-07-18 15:25
    关注

    Here's a solution using reflection. You have to further develop it if you need more complex structures with embedded struct fields and such.

    http://play.golang.org/p/iTaDgsdSaI

    package main
    
    import (
        "encoding/json"
        "fmt"
        "reflect"
    )
    
    type M map[string]interface{} // just an alias
    
    var Record = []byte(`{ "bit_size": 8, "secret_key": false }`)
    
    type DB struct {
        NumBits int  `json:"bit_size"`
        Secret  bool `json:"secret_key"`
    }
    
    type User struct {
        NumBits int `json:"num_bits"`
    }
    
    func main() {
        d := new(DB)
        e := json.Unmarshal(Record, d)
        if e != nil {
            panic(e)
        }
        m := mapFields(d)
        fmt.Println("Mapped fields: ", m)
        u := new(User)
        o := applyMap(u, m)
        fmt.Println("Applied map: ", o)
        j, e := json.Marshal(o)
        if e != nil {
            panic(e)
        }
        fmt.Println("Output JSON: ", string(j))
    }
    
    func applyMap(u *User, m M) M {
        t := reflect.TypeOf(u).Elem()
        o := make(M)
        for i := 0; i < t.NumField(); i++ {
            f := t.FieldByIndex([]int{i})
            // skip unexported fields
            if f.PkgPath != "" {
                continue
            }
            if x, ok := m[f.Name]; ok {
                k := f.Tag.Get("json")
                o[k] = x
            }
        }
        return o
    }
    
    func mapFields(x *DB) M {
        o := make(M)
        v := reflect.ValueOf(x).Elem()
        t := v.Type()
        for i := 0; i < v.NumField(); i++ {
            f := t.FieldByIndex([]int{i})
            // skip unexported fields
            if f.PkgPath != "" {
                continue
            }
            o[f.Name] = v.FieldByIndex([]int{i}).Interface()
        }
        return o
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

悬赏问题

  • ¥15 请提供一个符合要求的网页链接。
  • ¥20 用HslCommunication 连接欧姆龙 plc有时会连接失败。报异常为“未知错误”
  • ¥15 网络设备配置与管理这个该怎么弄
  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码