V
V
Vladimir Grabko2016-06-25 09:25:18
go
Vladimir Grabko, 2016-06-25 09:25:18

How to make json.Marshal/Unmarshal for complex map?

I needed to replicate map with cache to a file. It's very simple, I thought. It saves all "simple" (string, ... int) types normally, but as soon as the structure gets into the cache, problems begin. Now I have to manually encode it in json every time I add a structure to the cache (throughout the code ...). How to make the encoding of structures in json happen automatically in the replication function?
I did not succeed in zayuzat reflection.
The cache stores the map

type DB struct {
  Storage map[string]interface{}
  RW      *sync.RWMutex
}
var storage = map[string]*DB

Replication code
package cache

import (
  "time"

  "encoding/json"

  "os"
  "io/ioutil"
  "log"
  "sync"
)
type Replication map[string]map[string]interface{}
func ReplicationFileSystem(file string, timeRepl time.Duration) {
  SelectReplication(file)
  for {
    time.Sleep(timeRepl)
    replication(file)
  }
}
func SelectReplication(file string){
  log.Println("Cache replication: Start")
  var replication Replication
  val, err := ioutil.ReadFile(file)
  if err != nil {
    log.Fatal("Cache replication err: ", err)
  }
  err = json.Unmarshal(val, &replication)
  if err != nil {
    log.Fatal("Cache replication decode err: ", err)
  }

  rw.Lock()
  for key, dbs := range replication {
    database[key] = &DB{
      Storage: dbs,
      RW : &sync.RWMutex{},
    }

  }
  rw.Unlock()
  log.Println("Cache replication: Ok")
}
func replication(file string) {
  encode := Replication{
    "replication":map[string]interface{}{
      "replication": "",
    },
  }
  rw.RLock()
  for k, v := range database {
    encode[k] = v.Storage
  }
  rw.RUnlock()

  json, _ := json.Marshal(encode)
  saveFile(file, string(json))
}

func saveFile(file, raw string) {
  f, err := os.Create(file)
  if err != nil {
    return
  }
  defer f.Close()

  f.WriteString(raw)

}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexander Semchenko, 2016-06-27
@0xcffaedfe

What prevents declaring a structure as a json structure?

type Config struct {
  Database struct {
    DatabaseName     string `json:"database_name"`
    DatabasePassword string `json:"database_password"`
    DatabaseUser     string `json:"database_user"`
    DatabasePort     int    `json:"database_port"`
  } `json:"database"`
  Accounts struct {
    AutoCreate bool `json:"auto_create"`
  } `json:"accounts"`
  Client struct {
    BanTimeForBruteForcing int    `json:"ban_time_for_brute_forcing"`
    Host                   string `json:"host"`
    LoginTryBeforeBan      int    `json:"login_try_before_ban"`
    Port                   int    `json:"port"`
  } `json:"client"`
  Server struct {
    Pingpong          bool   `json:"pingpong"`
    Host              string `json:"host"`
    PingpongDelay     bool   `json:"pingpong_delay"`
    PingpongDelayTime int    `json:"pingpong_delay_time"`
    Port              int    `json:"port"`
  } `json:"server"`
}

If I understand you correctly.

M
Max Voronov, 2016-07-20
@RavenRage

If you need to transform complex structures according to some special logic, then it may make sense to use your own marshaling method. Here is a small rough example, but in general I think the idea can be conveyed correctly:

type Person struct {
  Id int
  Name string
}

func (p Person) MarshalJSON() ([]byte, error) {
  // Your custom logic
  return []byte(`{"name": "` + p.Name + `"}`), nil	
}

func main() {
  user := Person{Id: 1, Name: "Mr.Incognito"}
  json.NewEncoder(os.Stdout).Encode(user)
  // Вместо всей структуры выведет только {"name":"Mr.Incognito"}
}

Try it in sandbox: https://play.golang.org/p/SyVWaDtBR9

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question