bea*_*mit 16 reflection json go memcpy
我有一个存储JSON的数据库,以及一个提供外部API的服务器,通过HTTP帖子,可以更改此数据库中的值.数据库由内部的不同进程使用,因此具有共同的命名方案.
客户看到的密钥是不同的,但是使用数据库中的密钥(有未公开的密钥)将1:1映射.例如:
这是在数据库中:
{ "bit_size": 8, "secret_key": false }
Run Code Online (Sandbox Code Playgroud)
这是呈现给客户:
{ "num_bits": 8 }
Run Code Online (Sandbox Code Playgroud)
API可以根据字段名称进行更改,但数据库始终具有一致的键.
我在结构中将字段命名为相同,并为json编码器指定了不同的标志:
type DB struct {
NumBits int `json:"bit_size"`
Secret bool `json:"secret_key"`
}
type User struct {
NumBits int `json:"num_bits"`
}
Run Code Online (Sandbox Code Playgroud)
我正在使用encoding/json
Marshal/Unmarshal.
这reflect
是正确的工具吗?是否有更简单的方法,因为所有键都相同?我在想某种memcpy
(如果我保持用户字段的顺序相同).
这是使用反射的解决方案.如果您需要具有嵌入式结构字段等的更复杂结构,则必须进一步开发它.
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
}
Run Code Online (Sandbox Code Playgroud)
结构嵌入无法在这里有用吗?
package main
import (
"fmt"
)
type DB struct {
User
Secret bool `json:"secret_key"`
}
type User struct {
NumBits int `json:"num_bits"`
}
func main() {
db := DB{User{10}, true}
fmt.Printf("Hello, DB: %+v\n", db)
fmt.Printf("Hello, DB.NumBits: %+v\n", db.NumBits)
fmt.Printf("Hello, User: %+v\n", db.User)
}
Run Code Online (Sandbox Code Playgroud)
http://play.golang.org/p/9s4bii3tQ2
小智 7
buf := bytes.Buffer{}
err := gob.NewEncoder(&buf).Encode(&DbVar)
if err != nil {
return err
}
u := User{}
err = gob.NewDecoder(&buf).Decode(&u)
if err != nil {
return err
}
Run Code Online (Sandbox Code Playgroud)