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

11

我正在尝试使用JSON.Marshal()在golang中从一个Map中创建JSON字符串。但是,整数值以双引号括起来的字符串形式显示。

我的代码输出:

{ "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类型的值。类似map[string]map[string]{}。

我该怎么做呢?先感谢您。

Harry

4个回答

8

如果您无法使用正确类型的结构体描述您的数据,则考虑使用值为 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
谢谢您的快速回答。完美地运作! - Harry

2
我们可以按照以下方式声明变量,用于将整数、字符串混合映射。"mix mapping" 可以翻译为 "混合映射"。
var variable_name = map[string]interface{}{}

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

1

我同意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))
}

谢谢nulldog。是的,我正在使用mongodb查询。我之前不知道这个导入,但它看起来非常有用。 - Harry

0
你的代码按预期工作:map[string]map[string]string{} 只包含字符串值,因此 json.Marshal(interface{}) 返回带有序列化的 string 值的 json 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"
}

附言:我不建议您使用map[string]map[string]interface{},因为在这种情况下,您需要有自定义的Unmarshaller(来填充您的map)。使用结构体,您可以通过以下方式对其进行解组:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接