如何将嵌套结构编组为平面 JSON

How to marshal nested struct to flat JSON

我正在尝试将具有多个相同结构的嵌套结构编组为平面 JSON 结构 E.G.

type A struct {
    Value float64
    Unit  string
}
type B struct {
    p1 string `json:p1`
    p2 int    `json:p1`
    ...
    a1 A      `json:"a1,omitempty"`
    a2 A      `json:"a1,omitempty"`
    ...
}

调用 json.Marshall(B) 的目的是获得一个 json 结构,该结构使用上述代码打印平面结构。所以不是

{
    "p1": "...",
    "p2": 1,
    ...
    "a1": {...}
    "a2": {...}
    ...
}

我会得到类似于

的结构
{
    "p1": "...",
    "p2": 1,
    ...
    "a1": 1.1,
    "a1_u": "unit",
    "a2": 1.2,
    "a2_u": "unit",
    ...
}

我看过嵌入的概念,但只有当 B 中只有一个 A 时才有效。而且仍然无法完全实现我的愿望。

在 JSON 中需要这种结构的原因很遗憾是没有商量余地的。而需要用到的结构体会包含大量的A{}。已知它们将包含什么,因此创建和使用如下所示的结构是一种选择。但随着项目的增长,它只会造成混乱和维护地狱。

type C struct {
    p1 string `json:p1`
    p2 int    `json:p1`
    ...
    a1   float64 `json:"a1,omitempty"`
    a1_u string  `json:"a1_u,omitempty"`
    a2   float64 `json:"a2,omitempty"`
    a2_U string  `json:"a2_u,omitempty"`
    ...
}

可以选择为 B{}A{} 编写自定义编组,这可能可以满足我的需要,问题是我们需要一堆不同的结构,例如 B{}它们非常相似,我相信应该有一种方法可以概括解决这个问题。

想到使用与反射相关的东西。但是由于我对 GO 很陌生,所以我还没有找到解决方案。所有花在谷歌搜索上的努力只会让我看到相反的结果。

提前感谢任何帮助,如果是“无法完成”。

*编辑

B 并通过扩展 C 意味着能够包含任意数量的 A 以及一些原语。将来也可以有 DE 类型,每个都包含不常见数量的 A 和原语。或者实际上具有这些约束的任意数量的结构。我想避免的是为每个新结构编写一个 Marhaller。

编写自定义封送拆收器。示例:

type A struct {
    Value float64
    Unit  string
}

type B struct {
    a1 A
    a2 A
}

func (b *B) MarshalJSON() ([]byte, error) {
    intermediate := map[string]interface{}{
        "a1":   b.a1.Value,
        "a1_u": b.a1.Unit,
        "a2":   b.a2.Value,
        "a2_u": b.a2.Unit,
    }
    return json.Marshal(intermediate)
}

根据您对这段代码的预期 grow/expand 随着时间的推移,您也许可以使用某种循环或反射,但在不知道扩展计划的情况下,不可能具体。