json - 在 golang 中持久化嵌套结构

标签 json pointers go struct

我想添加持久化并从 json 初始化。 我正在尝试保存/加载嵌套结构并收到“ fatal error :堆栈溢出”。

据我了解,原因是父结构和子结构都有指向彼此的指针,并且 json 库正在进入循环。我需要指向 Parent 的指针,因为需要从 child 那里访问它。

我知道这是一个常见问题,解决它的最佳方法是什么?

type Mcloud struct {
    Projects map[string]*Project `json:"Projects"`
    Workdir  string
}

type Project struct {
    Name     string
    Networks map[string]Network
    Parent   *Mcloud
    TFC      TFConf
}

func newMcloud() *Mcloud {
    mc := &Mcloud{
        Projects: make(map[string]*Project),
        Workdir:  defaultWorkDir,
    }
    mc.load(statefile)

    return mc
}


func (mc *Mcloud) addProject(n string) {
    mc.Projects[n] = &Project{
        Name:     n,
        Networks: make(map[string]Network),
        Parent:   mc,
    }
    mc.Projects[n].addTFConf()
}

//save saves state to statefile
func (mc *Mcloud) save(f string) (err error) {
    if jsonState, err := json.Marshal(mc); err != nil {
        fmt.Println("Was not able to marshal")
        log.Fatal(err)
    } else {
        if err := ioutil.WriteFile(f, jsonState, 0666); err != nil {
            fmt.Println("Was not able to write state to", f, "!")
            log.Fatal(err)
        }
        fmt.Println("Save function saves: \n", mc, "to file ", f)
    }

    return err
}

func (mc *Mcloud) load(f string) (err error) {
    var bytestate []byte

    if bytestate, err = ioutil.ReadFile(f); err == nil {
        err = json.Unmarshal(bytestate, &mc)
    }

    return err
}

获取

runtime: goroutine stack exceeds 1000000000-byte limit fatal error: stack overflow

runtime stack: runtime.throw(0x149cdfe, 0xe) /usr/local/Cellar/go/1.11.1/libexec/src/runtime/panic.go:608 +0x72 runtime.newstack() /usr/local/Cellar/go/1.11.1/libexec/src/runtime/stack.go:1008 +0x729 runtime.morestack() /usr/local/Cellar/go/1.11.1/libexec/src/runtime/asm_amd64.s:429 +0x8f

goroutine 1 [running]: runtime.heapBitsSetType(0xc042a7df20, 0x60, 0x60, 0x1486e60) /usr/local/Cellar/go/1.11.1/libexec/src/runtime/mbitmap.go:911 +0xa30 fp=0xc02243c388 sp=0xc02243c380 pc=0x1016cd0 runtime.mallocgc(0x60, 0x1486e60, 0x1, 0x0) /usr/local/Cellar/go/1.11.1/libexec/src/runtime/malloc.go:933 +0x540 fp=0xc02243c428 sp=0xc02243c388 pc=0x100d4f0 runtime.newobject(0x1486e60, 0x0) /usr/local/Cellar/go/1.11.1/libexec/src/runtime/malloc.go:1032 +0x38 fp=0xc02243c458 sp=0xc02243c428 pc=0x100db28 reflect.mapiterinit(0x14206a0, 0xc00009d830, 0x0)

最佳答案

首先你需要告诉 encoding/json 跳过父字段,你可以用 json:"-" 标签来做到这一点。

然后在反编码过程中,在加载父项的所有子项后,循环遍历子项并设置它们的父项,您可以通过实现 json.Unmarshaler 将此作为反编码过程的一部分进行界面。

type Mcloud struct {
    Projects map[string]*Project `json:"Projects"`
    Workdir  string
}

type Project struct {
    Name     string
    Networks map[string]Network
    Parent   *Mcloud `json:"-"` // ignore on un/marshal
    TFC      TFConf
}

func (m *Mcloud) UnmarshalJSON(data []byte) error {
    type tmp Mcloud
    if err := json.Unmarshal(data, (*tmp)(m)); err != nil {
        return err
    }

    // set Parent of all projects
    for _, p := range m.Projects {
        p.Parent = m
    }
    return nil
}

关于json - 在 golang 中持久化嵌套结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53196055/

相关文章:

angularjs - Angular $http.get 错误,意外 token

ios - 如何在键是动态的 Swift 4 中为 JSON 编写 Decodable?

将 char 数组转换为结构指针

c++ - 输出指针的 const 前缀

oracle - 如何在Godror中执行具有多个查询的文件?

java - 为什么我应该使用 gRPC 而不是 IPC/Simple websocket?

javascript - 相同数据的 Ajax 错误(解析器错误 : SyntaxError: JSON. 解析:JSON 数据第 1 行第 1 列出现意外字符)

java - 使用json.simple创建json对象

c++ - 指针互换性与具有相同地址

json - 无法将 json 数据反序列化为结构