简体   繁体   English

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

[英]How to marshal nested struct to flat JSON

I am trying to marshall a nested struct with several of the same structs to a flat JSON structure EG我正在尝试将具有几个相同结构的嵌套结构编组为平面 JSON 结构 EG

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"`
    ...
}

When calling json.Marshall(B) the goal is to get a json structure that is using the above code to print a flat structure.当调用json.Marshall(B)时,目标是获得使用上述代码打印平面结构的 json 结构。 So that instead of所以,而不是

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

I would get a structure similar to我会得到一个类似于

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

I have looked at the concept of embedding, but that would only work if there is only one A in B. And would still not fully accomplish what i wish.我已经研究过嵌入的概念,但这只有在 B 中只有一个 A 时才有效。而且仍然不能完全实现我的愿望。

The reason for the need of this structure in the JSON is sadly not negotiable. JSON 中需要这种结构的原因是不可协商的。 And the structs that need to be used will contain a large amount of A{} .而需要用到的结构体会包含大量的A{} It is known what they will contain, so creating and using a struct as below is an option.已知它们将包含什么,因此可以选择创建和使用如下结构。 But as the project grows, it only serves to confuse and create a maintenance hell.但随着项目的发展,它只会让人感到困惑并造成维护地狱。

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"`
    ...
}

There is the option of writing custom marshalling for B{} and A{} which could probably accomplish what I need, the issue is that we need a bunch of different structs like B{} that are similar enough that I believe there should be a way to generalise a solution to this.可以选择为B{}A{}编写自定义编组,这可能可以满足我的需要,问题是我们需要一堆不同的结构,比如B{} ,它们足够相似,我相信应该有一个方法来概括解决这个问题。

Thoughts go to using something relating to reflections.想法 go 使用与反射有关的东西。 But as I am quite new to GO I have not managed to figure out the solution.但由于我对 GO 很陌生,我还没有设法找出解决方案。 And all efforts spent googling only shows me the opposite.谷歌搜索所花费的所有努力只会让我看到相反的结果。

Thanks in advance for any help, event if it is "It cant be done".提前感谢您的任何帮助,如果它是“无法完成”的事件。

*EDIT *编辑

B and by extension C is meant to be able to contain an arbitrary number of A as well as some primitives. B和扩展C意味着能够包含任意数量的A以及一些原语。 In the future there can be type D and E as well, that each contain a non common amount of A and primitives.将来也可以有类型DE ,每个类型都包含不常见数量的A和原语。 Or in fact any number of structs with these constraints.或者实际上是具有这些约束的任意数量的结构。 What I am trying to avoid is writing a Marhaller for each new struct.我要避免的是为每个新结构编写一个 Marhaller。

Write a custom marshaler.编写一个自定义封送器。 Example:例子:

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)
}

Depending on how you expect this code to grow/expand over time, you may be able to use some kind of loop, or reflection, but without knowing the extension plans, it's impossible to be specific.根据您期望此代码随时间增长/扩展的方式,您可能能够使用某种循环或反射,但在不知道扩展计划的情况下,不可能具体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM