1

我正在编写一个端点来为 Geckoboard 返回数据,它的格式如下:

{
  "item": [
    {
      "value": "274057"
    },
    [
      "38594",
      "39957",
      "35316",
      "35913",
      "36668",
      "45660",
      "41949"
    ]
  ]
}

"item"是一个不同结构的数组。我将如何在 Go 中表示这些数据?

注意:这不是关于我将如何解组它,我需要生成这种格式。

4

2 回答 2

1

这些东西比你想象的要容易。对于普通读者来说,这并没有很好的记录。我会推荐ffjson正常的json寿。它以这样一种方式组成,除了库名称之外,您不需要更改语法。

这很容易:

type User struct {
    Id      int    `json:'id'`
    Name    string `json:name`
    SomeId1 int    `json:some_id_1`
    SomeId2 int    `json:some_id_2`
    SomeId3 int    `json:some_id_3`
    SomeId4 int    `json:some_id_4`
}

item := map[string]User{}
for i := 0; i < 10; i++ {
    item[strconv.itoa(i)] = User{i, "Username X", 38393, 29384, 12393, 123981}
}
buf, err := ffjson.Marshal(&item)

结构的缺点(即使是ffjson静止的)是reflection总是会被使用,在你需要高性能的时候,你会浪费大量的 CPU 周期。当您将其保留在地图上时,它ffjson比正常速度快 2-3 倍。json这样,库可以编译您编组的每个数据结构并重新使用它,而不是使用reflect.

于 2015-05-13T12:21:19.773 回答
1

有一种简单的方法可以创建一些数据结构的值,您知道要生成/复制的 JSON 输出:

获取您要生成的输出,并将其解组为map[string]interface{}. 您将获得一个映射值,当您编组时将产生您想要的输出。当您解组预期输出时,您可以检查结果映射值以了解您需要创建什么才能获得预期输出。

这也适用于您的情况。这是代码:

var m map[string]interface{}
err := json.Unmarshal([]byte(input), &m)
if err != nil {
    panic(err)
}
fmt.Printf("%+v\n", m)

res, err := json.MarshalIndent(m, "", "  ")
if err != nil {
    panic(err)
}
fmt.Println(string(res))

input您的 JSON 输入在哪里:

const input = `{
  "item": [
    {
      "value": "274057"
    },
    [
      "38594",
      "39957",
      "35316",
      "35913",
      "36668",
      "45660",
      "41949"
    ]
  ]
}`

该程序生成与您所需的输出(或输入)相同的输出:

map[item:[map[value:274057] [38594 39957 35316 35913 36668 45660 41949]]]
{
  "item": [
    {
      "value": "274057"
    },
    [
      "38594",
      "39957",
      "35316",
      "35913",
      "36668",
      "45660",
      "41949"
    ]
  ]
}

在Go Playground上尝试完整的应用程序。

分析未编组的地图值:

显然它有一个 key "item",它的值的类型:

fmt.Printf("%T\n", m["item"]); // Prints []interface{}

所以是一片。它有 2 个值,它们的类型:

fmt.Printf("%T\n", m["item"].([]interface{})[0]); // map[string]interface{}
fmt.Printf("%T\n", m["item"].([]interface{})[1]); // []interface{}

所以切片包含2个值:

  • 一张地图("value" : "274057"一对)
  • 和另一个切片(ID 或数字列表)

这是重现相同地图值的 Go 代码:

m := map[string]interface{}{
    "item": []interface{}{
        map[string]interface{}{"value": "274057"},
        []interface{}{"38594", "39957", "35316", "35913", "36668", "45660", "41949"},
    },
}

编组这会产生相同的 JSON 输出。

于 2015-05-13T12:38:27.173 回答