包含字符串和整数的 Golang 映射

Golang map containing both string and integer

我正在尝试使用 golang 中的 JSON.Marshal() 从地图创建一个 JSON 字符串。但是,int 值显示为用双引号括起来的字符串。

我的代码正在输出:

{ "age":
    {
        "$gt":"22",
        "$lt":"20"
    },
  "location":
    {
        "$eq":"london"
    },
  "name":{
        "$eq":"fred"
    }
}

而不是

{ "age":
    {
        "$gt":22,
        "$lt":20
    },
  "location":
    {
        "$eq":"london"
    },
  "name":{
        "$eq":"fred"
    }
}

我正在使用:

var output_map = map[string]map[string]string{}

//Populate map here

output_json, err := json.Marshal(output_map)

if err!= nil {
    fmt.Println("Error encoding JSON")
}

fmt.Println(output_json)

我的理解是 JSON.Marshal() 将正确打印整数(如果提供的话),但我的地图不包含整数。我可以将我的地图更改为 map[string]map[string]int{} 但它不会包含 'name' 和 'location'.

的字符串值

最终的问题是我需要地图同时包含 int 和 string 值。某种地图[string]地图[string]{}。

我怎样才能做到这一点?提前谢谢你。

哈利

如果您无法使用类型正确的结构来描述您的数据,请考虑使用值类型为 interface{}(基本上是任何类型)的映射:

output_map := map[string]map[string]interface{}{}

例如:

output_map := map[string]map[string]interface{}{
  "age": {
    "$gt": 18,
  },
  "location": {
    "eq": "London",
  },
}
bytes, err := json.MarshalIndent(&output_map, "", "  ")
if err != nil {
  panic(err)
}
// {
//   "age": {
//     "$gt": 18
//   },
//   "location": {
//     "eq": "London"
//   }
// }

当然,使用 interface{} 类型并不是最佳做法;然而,有时它是完成某些事情的唯一方法。

我同意 maerics,

map[string]interface{} 将是要走的路,如果你必须避免结构。

根据您的内容,我假设您正在处理 mongodb-查询。
所以也许下面的代码有帮助。

如果您要从 go 查询 mongodb,我会推荐 mgo-driver mgo.v2.
它实现了一个自定义类型 bson.M ,它与上面提到的相同,但也适用于查询数据库。

除此之外,它使代码更具可读性。

样本:

package main

import (
    "fmt"
    "gopkg.in/mgo.v2/bson"
    "encoding/json"
)

func main() {

    bsonMap := bson.M{
        "age": bson.M{
            "$gt": 22,
            "$lt": 20,
        },
        "location": bson.M{"$eq": "london",},
        "name":     bson.M{"$eq": "fred"},
    }

    bytes, err := json.Marshal(bsonMap)

    if err != nil {
        panic(err)
    }

    fmt.Println(string(bytes))
}

您的代码按预期工作:map[string]map[string]string{} 仅包含字符串值,因此 json.Marshal(interface{}) return json string 具有编组的 string 值。

我认为你应该使用 struct 而不是 map。只需创建一个结构,如下所示:

type Age struct {
    Gt  int `json:"gt"`
    Lt  int `json:"lt"`
}

type Person struct {
    Age         Age     `json:"age"`
    Location    string  `json:"location"`
    Name        string  `json:"name"`
}

并且只需使用标准 json.Marshal(interface{}) 方法对其进行编组。 (在此代码中不需要 json 标签,但如果您想更改序列化 json 字符串中的字段名称,则可以使用它)

我在 main() 中使用以下代码创建 test.go 文件:

person := Person{
    Age{
        22,
        20,
    },
    "London",
    "Fred",
}

serialized, e := json.Marshal(person)
if e != nil {
    fmt.Println(e)
    return
}

fmt.Println(string(serialized))

它 return 是这样的:

{
    "age":
    {
        "gt":22,
        "lt":20
    },
    "location":"London",
    "name":"Fred"
}

P.S. 我不建议您使用 map[string]map[string]interface{} 因为在这种情况下您需要自定义 Unmarshaller (以填满你的 map 回来)。使用结构,您可以通过这种方式解组它:

deserialized := Person{}
e = json.Unmarshal(serialized, &deserialized)
if e != nil {
    fmt.Println("can't deserialize:", e)
    return
}

我们可以像下面这样用整数、字符串来声明混合映射的变量。

var variable_name = map[string]interface{}{}

例如

var variable_name = map[string]interface{}{
        "name": c.String("name"),
        "age":  c.Int("age"),
}