如何将嵌套结构编组为平面 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
以及一些原语。将来也可以有 D
和 E
类型,每个都包含不常见数量的 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 随着时间的推移,您也许可以使用某种循环或反射,但在不知道扩展计划的情况下,不可能具体。
我正在尝试将具有多个相同结构的嵌套结构编组为平面 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
以及一些原语。将来也可以有 D
和 E
类型,每个都包含不常见数量的 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 随着时间的推移,您也许可以使用某种循环或反射,但在不知道扩展计划的情况下,不可能具体。