json - 对嵌套结构使用自定义解码时,GoLang 结构无法正确解码

标签 json go struct nested unmarshalling

我们需要为嵌套在不需要自定义解码器的多个其他结构中的结构使用自定义解码器。我们有很多结构类似于下面定义的 B 结构(类似于嵌套 A)。代码的输出是 true false 0(预期的 true false 2)。有什么想法吗?


Go Playground 示例 here .

package main

import (
    "fmt"
    "encoding/json"
)

type A struct {
    X bool `json:"x"`
    Y bool `json:"y"`
}

type B struct {
    A
    Z int `json:"z"`
}

func (a *A) UnmarshalJSON(bytes []byte) error {
    var aa struct {
        X string `json:"x"`
        Y string `json:"y"`
    }
    json.Unmarshal(bytes, &aa)

    a.X = aa.X == "123"
    a.Y = aa.Y == "abc"
    return nil
}

const myJSON = `{"x": "123", "y": "fff", "z": 2}`

func main() {
    var b B
    json.Unmarshal([]byte(myJSON), &b)
    fmt.Print(b.X," ",b.Y," ",b.Z)
}

编辑:问题被标记为重复 here但是使 A 成为显式字段会使我们的 API 变得困惑。此外,在将 A 设为显式字段后,结果为 false false 2,因此它根本没有帮助。

最佳答案

由于 B 嵌入了 AA.UnmarshalJSON() 被公开为 B.UnmarshalJSON()。因此,B 实现了 json.Unmarshaler,因此 json.Unmarshal() 调用了 B.UnmarshalJSON() 只解码 A 的字段。这就是 B.Z 没有从 JSON 中设置的原因。

这是我能想到的最简单的方法,可以根据您不更改 A 中的数据类型的限制使其工作:

  1. 让 B 嵌入另一个包含 A 中不包含的字段的结构 C。
  2. 为 B 编写一个 UnmarshalJSON() 方法,该方法将相同的 JSON 解码为 B.A 和 B.C。使用不在 A 中的字段定义另一个类型 C 的优点是您可以将其解码委托(delegate)给 json 包。

使用新的 B.UnmarshalJSON() 方法,您现在可以完全控制解码 A 之外的字段。

type A struct {
    X bool `json:"x"`
    Y bool `json:"y"`
}

func (a *A) UnmarshalJSON(bytes []byte) error {
    // the special unmarshalling logic here
}

type C struct {
    Z int `json:"z"`
}

type B struct {
    A
    C
}

func (b *B) UnmarshalJSON(bytes []byte) error {
    if err := json.Unmarshal(bytes, &b.A); err != nil {
        return err
    }
    if err := json.Unmarshal(bytes, &b.C); err != nil {
        return err
    }
    return nil
}

关于json - 对嵌套结构使用自定义解码时,GoLang 结构无法正确解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52294027/

相关文章:

javascript - 即使最大宽度设置为 100%,为什么我的 (json) 图像仍超出边框/容器?

javascript - 在javascript对象字面量中,如何引用具有相同级别或更高级别的函数?

javascript - 在移动混合应用程序中存储 JSON 数据的最佳方式是什么?

Golang reflect,如何获取map值类型?

c++ - 无法访问类内的结构成员

C:结构体中的动态 int 数组 - 内存释放

java - 使用 Google Media Framework Exoplayer 的视频播放器空指针异常

mongodb - 需要帮助使用 golang 在我的 mongodb 数据库中存储类型接口(interface)的映射

递归,并且不通过 return 语句结束递归

c - curr_node.ptr = &(next_node.ptr); 之间的区别和 curr_node.ptr = &next_node