【问题标题】:Golang map containing both string and integer包含字符串和整数的 Golang 映射
【发布时间】:2018-05-22 00:47:24
【问题描述】:

我正在尝试使用 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 值。某种地图[字符串]地图[字符串]{}。

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

哈利

【问题讨论】:

    标签: json go types marshalling


    【解决方案1】:

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

    【讨论】:

    • 感谢您的快速回答。完美运行!
    【解决方案2】:

    我同意 maerics,

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

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

    如果你要从 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))
    }
    

    【讨论】:

    • 感谢 nulldog。是的,我正在使用 mongodb 查询。我不知道这个导入,但它看起来非常有用
    【解决方案3】:

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

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

    例如

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

    【讨论】:

      【解决方案4】:

      您的代码按预期工作: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字符串中的字段名称,可以使用它)

      我在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))
      

      它会返回这个:

      {
          "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
      }
      

      【讨论】:

        猜你喜欢
        • 2018-02-20
        • 1970-01-01
        • 2018-07-02
        • 1970-01-01
        • 1970-01-01
        • 2021-11-15
        • 1970-01-01
        • 1970-01-01
        • 2013-08-04
        相关资源
        最近更新 更多