User Tools

Site Tools


Structure encoder to key-value

kvenc.go
/*
 * Copyright Oleg Borodin  <borodin@unix7.org>
 *
 */
 
package main
 
import (
    "encoding/json"
    "fmt"
    "reflect"
)
 
const tagName   string = "mytag"
const idTagName string = "id"
 
type User struct {
    Id      int         `mytag:"id"      json:"id"`
    Name    string      `mytag:"name"    json:"name"`
    Pass    string      `mytag:"pass"    json:"pass"`
    Phone   string      `mytag:"pnum"    json:"pnum"`
}
 
func encoder(prefix string, s interface{}) map[string]string {
    t := reflect.TypeOf(s)
 
    keymap := make(map[string]string)
 
    var id int64
    for i := 0; i < t.NumField(); i++ {
        tag := t.Field(i).Tag.Get(tagName)
        if tag == idTagName {
            r := reflect.ValueOf(s)
            f := reflect.Indirect(r).Field(i)
            id = f.Int()
            break
        }
    }
 
    for i := 0; i < t.NumField(); i++ {
        tag := t.Field(i).Tag.Get(tagName)
        if tag == idTagName {
            continue
        }
        r := reflect.ValueOf(s)
        f := reflect.Indirect(r).Field(i)
        key := fmt.Sprintf("%s:%d:%s", prefix, id, tag)
        value := f.String()
        keymap[key] = value
    }
    return keymap
}
 
func decoder(prefix string, id int, keymap map[string]string, s interface{})  {
    v := reflect.ValueOf(s)
    i := reflect.Indirect(v)
    t := i.Type()
 
    for i := 0; i < t.NumField(); i++ {
        tag := t.Field(i).Tag.Get(tagName)
        if tag == idTagName {
            reflect.ValueOf(s).Elem().Field(i).SetInt(int64(id))
            continue
        }
        key := fmt.Sprintf("%s:%d:%s", prefix, id, tag)
        reflect.ValueOf(s).Elem().Field(i).SetString(keymap[key])
    }
}
 
func main() {
    iuser := User{ Id: 1, Name: "qwert", Pass: "12345", Phone: "1-555-1234" }
 
    prefix := "user"
 
    keymap := encoder(prefix, iuser)
 
    for key := range keymap {
        value := keymap[key]
        fmt.Println(key, "=", value)
    }
 
    ouser := &User{}
    decoder(prefix, 1, keymap, ouser)
 
    jsonBytes, _ := json.Marshal(ouser)
    fmt.Println(string(jsonBytes))
}
//EOF

Out

$ go run kvenc.go
user:1:name = qwert
user:1:pass = 12345
user:1:pnum = 1-555-1234
{"id":1,"name":"qwert","pass":"12345","pnum":"1-555-1234"}