转换 Go 映射到 json

我尝试用 encoding/json Marshall 将 Go 映射转换为 json 字符串,但结果是一个空字符串。

这是我的密码:

package main


import (
"encoding/json"
"fmt"
)


type Foo struct {
Number int    `json:"number"`
Title  string `json:"title"`
}


func main() {
datas := make(map[int]Foo)


for i := 0; i < 10; i++ {
datas[i] = Foo{Number: 1, Title: "test"}
}


jsonString, _ := json.Marshal(datas)


fmt.Println(datas)
fmt.Println(jsonString)
}

我的输出是:

map[9:{1 test} 2:{1 test} 7:{1 test} 3:{1 test} 4:{1 test} 5:{1 test} 6:{1 test} 8:{1 test} 0:{1 test} 1:{1 test}]


[]

我真不知道我哪里错了,谢谢你的帮助。

182118 次浏览

如果你发现了这个错误,你会看到这个:

jsonString, err := json.Marshal(datas)
fmt.Println(err)


// [] json: unsupported type: map[int]main.Foo

问题是在 JSON 你不能用整数作为键,这是被禁止的。相反,您可以事先将这些值转换为字符串,例如使用 strconv.Itoa

更多细节请看这篇文章: https://stackoverflow.com/a/24284721/2679935

它实际上告诉您出了什么问题,但是您忽略了它,因为您没有检查从 json.Marshal返回的错误。

json: unsupported type: map[int]main.Foo

JSON 规范只支持对象键的字符串,虽然 javascript 不会对此过于挑剔,但它仍然是非法的。

你有两个选择:

1使用 map[string]Foo并将索引转换为字符串(例如使用 fmt.Sprint) :

datas := make(map[string]Foo, N)


for i := 0; i < 10; i++ {
datas[fmt.Sprint(i)] = Foo{Number: 1, Title: "test"}
}
j, err := json.Marshal(datas)
fmt.Println(string(j), err)

2简单地使用一个切片(javascript 数组) :

datas2 := make([]Foo, N)
for i := 0; i < 10; i++ {
datas2[i] = Foo{Number: 1, Title: "test"}
}
j, err = json.Marshal(datas2)
fmt.Println(string(j), err)

playground

由于这个问题已经提出/最后一次回答,因此通过使用 短信收发员文本编辑器接口 给你,增加了对 json Marshall/UnMarshall 映射的非字符串键类型的支持。您只需要为您的键类型实现这些接口,然后 json.Marshal就可以按预期工作了。

package main


import (
"encoding/json"
"fmt"
"strconv"
)


// Num wraps the int value so that we can implement the TextMarshaler and TextUnmarshaler
type Num int


func (n *Num) UnmarshalText(text []byte) error {
i, err := strconv.Atoi(string(text))
if err != nil {
return err
}
*n = Num(i)
return nil
}


func (n Num) MarshalText() (text []byte, err error) {
return []byte(strconv.Itoa(int(n))), nil
}


type Foo struct {
Number Num    `json:"number"`
Title  string `json:"title"`
}


func main() {
datas := make(map[Num]Foo)


for i := 0; i < 10; i++ {
datas[Num(i)] = Foo{Number: 1, Title: "test"}
}


jsonString, err := json.Marshal(datas)
if err != nil {
panic(err)
}


fmt.Println(datas)
fmt.Println(jsonString)


m := make(map[Num]Foo)
err = json.Unmarshal(jsonString, &m)
if err != nil {
panic(err)
}


fmt.Println(m)
}


产出:

map[1:{1 test} 2:{1 test} 4:{1 test} 7:{1 test} 8:{1 test} 9:{1 test} 0:{1 test} 3:{1 test} 5:{1 test} 6:{1 test}]
[123 34 48 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 49 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 50 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 51 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 52 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 53 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 54 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 55 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 56 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 44 34 57 34 58 123 34 110 117 109 98 101 114 34 58 34 49 34 44 34 116 105 116 108 101 34 58 34 116 101 115 116 34 125 125]
map[4:{1 test} 5:{1 test} 6:{1 test} 7:{1 test} 0:{1 test} 2:{1 test} 3:{1 test} 1:{1 test} 8:{1 test} 9:{1 test}]
data := map[string]interface{}
jsonByte, err := json.Marshal(data)
if err != nil{
log.Fatal(err)
}
jsonString := string(jsonByte)
fmt.Println(jsonString) // will be printing data map in json formate.

这种行为随着时间的推移而改变。我使用的是 go v1.16.5,我可以很高兴地将 int 类型作为 JSON 键传入。我现在已经尝试了同样的问题,我可以看到下面的结果。文本编辑器文本编辑器接口添加了非字符串键的类型转换。更多信息,您可以访问这个 https://golang.org/pkg/encoding/json/#Marshal

type Foo struct {
Number int    `json:"number"`
Title  string `json:"title"`
}


datas := make(map[int]Foo)


for i := 0; i < 5; i++ {
datas[i] = Foo{Number: 1, Title: "test"}
}


jsonString, _ := json.Marshal(datas)


fmt.Println("Datasets Result : ", datas)
fmt.Println("Marshal Datasets Result : ", string(jsonString), err)


m := make(map[int]Foo)
err = json.Unmarshal(jsonString, &m)
if err != nil {
panic(err)
}


fmt.Println("Unmarshal JSON Result : ", m)

产出:

Datasets Result map : [0:{1 test} 1:{1 test} 2:{1 test} 3:{1 test} 4:{1 test}]


Marshal Datasets Result : {"0":{"number":1,"title":"test"},"1":{"number":1,"title":"test"},"2":{"number":1,"title":"test"},"3":{"number":1,"title":"test"},"4":{"number":1,"title":"test"}} <nil>


Unmarshal JSON Result :  map[0:{1 test} 1:{1 test} 2:{1 test} 3:{1 test} 4:{1 test}]