如何将映射嵌入到结构中,使其具有平面 json 表示

How to embed a map into a struct so that it has a flat json representation

为了创建类似 table 的结构,我在之前的应用程序中将我的行数据序列化为以下格式:

{ "key1": "...", "key2": "...", "15/04": 1.3, "15/05": 1.2, .... "17/08": 0.8 }

现在我正在尝试用Go重写它,以便通过实践经验学习这门语言。在 Go 中,可以通过将两个结构嵌入到另一个结构中来将它们组合在一起。从该结构中编组的 json 将具有平面结构,即生成的 json 对象将具有第一个和第二个结构的字段的并集,而无需嵌套。这是一个例子:https://play.golang.org/p/jbJykip7pw (from http://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/)

我想我也可以将映射嵌入到结构中,这样我就可以使用以下类型定义在 json 之上编组:

type Row struct {
    key1 string
    key2 string
    RowData
}

type RowData map[string]float64

...
func main() {
    row := Row{
        "...",
        "...",
        RowData{
            "15/04": 1.3, "15/05": 1.2, .... "17/08": 0.8,
        },
    }
}

但这在我的 'Row' 对象中创建了一个字段 'RowData' 字段,而不是将 RowData 中的条目附加到我想要的平面 json 对象中:

{ "key1": "...", "key2": "...", "RowData": { "15/04": 1.3, "15/05": 1.2, .... "17/08": 0.8 } }

我想知道,是否有一种方法可以将映射或切片嵌入到结构中,以便生成的 json 对象是扁平的,而无需在类型 [=15] 上定义 MarshalJSON 函数=]?

简短的回答是否定的。该语言不允许您在结构中嵌入任何一种类型(切片或映射)。

只需使用一个 map[string]interface{}。处理 "key1" 和 "key2" 的值是字符串而其他所有内容都是其他地方的浮点数这一事实。这确实是您获得该输出的唯一方式。您可以使问题变得更复杂,超出这个范围(比如转换成更像您的类型或其他类型),但是如果您不愿意实施 MarshalJSON 唯一会产生您想要的结果的模型是map[string]interface{}

我知道已经有一个可接受的答案,但实际上你可以获得指定的 "desired flat json object."

"RowData" 不完全是 map[string]float;获取它的类型将产生 "main.RowData" (如果它在包 main 中)。它可以嵌入到结构中。举个例子,改编自原文 post:

package main

import (

    "encoding/json"
    "fmt"
)

type Row struct {
    Key1 string
    Key2 string
    RowData
}

type RowData map[string]float64

func main() {
    row := Row{
        RowData: make(map[string]float64),
    }
    row.RowData["15/04"] = 1.3
    row.RowData["15/05"] = 1.2
    row.RowData["17/08"] = 0.8
    row.Key1 = "value one"
    row.Key2 = "value two"

    flatJSON, _ := json.Marshal(row)
    fmt.Println(string(flatJSON))
}

这将产生:

{"Key1":"value one","Key2":"value two","RowData":{"15/04":1.3,"15/05":1.2,"17/08":0.8}}

字段名称必须大写才能导出,但您可以使用结构标签使它们与问题中指定的确切字符串匹配。