json - 在 Go 中,如何将 JSON 对象数组转换为具有默认值的结构数组?

标签 json go struct slice

我正在开发一个可以接收由 JSON 对象数组组成的 POST 的 Go API。 POST 的结构类似于:

[
  {
    "name":"Las Vegas",
    "size":14
  },
  {
    "valid": false,
    "name":"Buffalo",
    "size":63
  }
]  

假设我有以下结构:

type Data {
    Valid    bool
    Name     string
    Size     float64
}

我想创建一堆 Data 并将 Valid 设置为 true ,只要它实际上没有在 JSON 中指定为 错误。如果我只做一个,我可以使用 How to specify default values when parsing JSON in Go ,但是为了完成其中的未知数量,我唯一能想到的是:

var allMap []map[string]interface{}
var structs []Data
for _, item := range allMap {
  var data Data
  var v interface{}
  var ok bool
  if v, ok := item["value"]; ok {
    data.Valid = v
  } else {
    data.Valid = true
  }
  id v, ok := item["name"]; ok {
    data.Name = v
  }
  ...
  structs = append(structs, data)
}
return structs

现在我实际使用的结构有 14 个字段,其中一些具有我想要分配默认值的值,其他的可以留空,但所有这些都必须通过使用这种方法进行迭代。

有没有更好的办法?

最佳答案

您可以使用 json.RawMessage类型以延迟解码某些 JSON 文本值。如果您使用此类型,则 JSON 文本将存储在其中而不进行解码(因此您可以稍后根据需要解码此片段)。

因此,在您的情况下,如果您尝试解码成这样的 RawMessage 片段,您可以使用您在问题中链接的技术,即您可以迭代原始值片段(这是每个 Data 的 JSON 文本),创建一个 Data 结构,其中包含您想要的值作为缺失值的默认值,并将 slice 元素解码到这个准备好的结构中。就这样。

看起来像这样:

allJson := []json.RawMessage{}
if err := json.Unmarshal(src, &allJson); err != nil {
    panic(err)
}

allData := make([]Data, len(allJson))
for i, v := range allJson {
    // Here create your Data with default values
    allData[i] = Data{Valid: true}
    if err := json.Unmarshal(v, &allData[i]); err != nil {
        panic(err)
    }
}

Go Playground 上试试.

注释/变体

为了提高效率(避免复制结构),您还可以将 allData 设为上面示例中的指针 slice ,如下所示:

allData := make([]*Data, len(allJson))
for i, v := range allJson {
    // Here create your Data with default values
    allData[i] = &Data{Valid: true}
    if err := json.Unmarshal(v, allData[i]); err != nil {
        panic(err)
    }
}

如果您想继续使用非指针,为了提高效率,您可以在 slice 元素本身中“准备”您想要的默认值,如下所示:

allData := make([]Data, len(allJson))
for i, v := range allJson {
    // Here set your default values in the slice elements
    // Only set those which defer from the zero values:
    allData[i].Valid = true
    if err := json.Unmarshal(v, &allData[i]); err != nil {
        panic(err)
    }
}

关于json - 在 Go 中,如何将 JSON 对象数组转换为具有默认值的结构数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33050511/

相关文章:

c# - 使用索引器访问结构?

c - 在 realloc 中重新分配

android - 发送 Json POST Android - 未添加数据

json - 将json行数据分成多列 Pandas 数据框

xml - 使用 Go 的 xml 包编码 DIDL-Lite

go - 如何获得时间。滴答立即滴答

struct - 如何在 Go 中从结构体创建 []string

javascript - 如何将一种格式的json转换为另一种格式

javascript - 带有 JSON 数据源的 jQuery DataTables 插件在全局搜索上接受多个 POST 请求

go - 如何在go中扩展模板?