VGrabko
@VGrabko
Golang, Php, Js

Как сделать json.Marshal/Unmarshal для сложного мапа?

Мне понадобилось делать репликацию map с кешем в файл. Всё очень просто подумал я. Все "простые" (string, ... int) типы оно сохраняет по нормальному но как только в кеш попадает структура то начинаются проблемы. Сейчас мне приходится при каждом добавлении структуры в кеш ручками её кодировать в json (по всему коду...). Как сделать чтобы кодирование структур в json происходило автоматически в функции репликации?

Заюзать рефлекцию у меня не вышло.

Кеш хранит мап
type DB struct {
	Storage map[string]interface{}
	RW      *sync.RWMutex
}
var storage = map[string]*DB

Код репликации
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)

}

  • Вопрос задан
  • 1456 просмотров
Пригласить эксперта
Ответы на вопрос 2
0xcffaedfe
@0xcffaedfe
Developer & Reverser
Что мешает объявить структуру как json структуру?
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"`
}


Если я правильно тебя понял.
Ответ написан
RavenRage
@RavenRage
Если нужно преобразовывать сложные структуры по какой-то особой логике, то возможно имеет смысл использовать свой метод маршалинга. Вот небольшой грубый пример, но в целом думаю идею сможет донести верно:
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"}
}

Попробовать в сэндбоксе: https://play.golang.org/p/SyVWaDtBR9
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы