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

时间:2017-12-07 20:15:39

标签: json go types marshalling

我正在尝试使用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'的字符串值。

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

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

哈利

4 个答案:

答案 0 :(得分:3)

如果您无法使用正确类型的结构描述数据,请考虑使用值为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{}类型不是最佳做法;然而,它有时是完成某些事情的唯一方法。

答案 1 :(得分:1)

我同意maerics,

如果你必须避免使用结构,那么

map[string]interface{}就可以了。

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

如果您要从中查询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))
}

答案 2 :(得分:1)

我们可以声明整数和字符串混合映射的变量,如下所示。

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

例如

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

答案 3 :(得分:0)

您的代码按预期工作:map[string]map[string]string{}仅包含字符串值,因此json.Marshal(interface{})返回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字符串中的字段名称,则可以使用它。

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

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

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

fmt.Println(string(serialized))

然后返回:

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

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

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