将嵌套地图编组到JSON中

将嵌套地图编组到JSON中

问题描述:

I'm trying to marshal this nested map into a JSON string.

map[
  description:Foo Bar
  url:http://foobar.co.uk
  theme_color:#1b1b1b
  markdown:kramdown
  sass:map[
    style:compressed
  ]
  collections:map[
    projects:map[
      output:true
      permalink:/project/:path
    ]
    jobs:map[
      output:true
      permalink:/job/:path
    ]
  ]
  title:Foo Bar
  email:foo@foobarco.uk
]

(Cleaned up output from fmt.Printf("%v", m))

Initially a config file is read and parsed to produce the map, so I don't know the fields in advance, meaning I can't(?) use a struct.

Unmarshalling from YAML into this map of map[string]interface{} works fine, but when I pass this map to json.Marshal, I get the following error.

json: unsupported type: map[interface {}]interface{}

From reading around, I can see that this error is thrown because JSON only supports string keys. What's confusing me, is that the map above doesn't seem to have any non-string keys.

If I remove the nested sass and collections keys, it marshals without any issues.

Is it possible to do some sanity check on the map to confirm that all the keys are infact string and not just interface{} looking like strings?

我正尝试将嵌套的地图编组为JSON字符串。 p>

  map [
描述:Foo Bar 
 URL:http://foobar.co.uk 
 theme_color:#1b1b1b 
 markdown:kramdown 
 sass:map [
 style:compressed 
]  
集合:地图[
项目:地图[
输出:true 
永久链接:/ project /:path 
] 
工作:地图[
输出:true 
永久链接:/ job /:path \  n] 
] 
标题:Foo Bar 
电子邮件:foo@foobarco.uk 
] 
  code>  pre> 
 
 

(已清除 fmt中的输出。 Printf(“%v”,m) code>) p>

最初会读取并解析一个配置文件以生成地图,所以我事先不知道这些字段,这意味着 我不能(?)使用结构。 p>

从YAML解组到此 map [string] interface {} code>映射中可以正常工作,但是当我通过时 将此地图映射到 json.Marshal code>时,出现以下错误。 p>

  json:不支持的类型:map [interface {}] interface {} 
   code>  pre> 
 
 

通过阅读,我 可以看到抛出此错误,因为JSON仅支持字符串键。 令我感到困惑的是,上面的地图似乎没有任何非字符串键。 p>

如果我删除嵌套的 sass code>和 collections code>键,它可以封送,没有任何问题。 p>

是否可以在地图上进行一些完整性检查,以确认所有键都是有效的 string code> 而不只是 interface {} code>看起来像字符串? p> div>

Most likely, the sub-maps are being created as map[interface{}]interface{} by the YAML parser.

Print out your map with "%#v" instead of "%v" and you will see the types.

Here's an example

package main

import "fmt"

func main() {
    a := map[string]interface{}{
        "A": map[interface{}]interface{}{
            "B": 123,
        },
    }
    fmt.Printf("%#v
",a)
}

Produces:

map[string]interface {}{"A":map[interface {}]interface {}{"B":123}}