将Go地图转换为json

时间:2014-07-09 11:42:54

标签: json go

我尝试将我的Go地图转换为带有encoding/json Marshal的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}]

[]

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

5 个答案:

答案 0 :(得分:74)

如果您发现错误,您会看到:

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

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

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

有关详情,请参阅此帖子:https://stackoverflow.com/a/24284721/2679935

答案 1 :(得分:23)

它实际上会告诉您错误,但您忽略了它,因为您没有检查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

答案 2 :(得分:1)

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.

答案 3 :(得分:0)

自从这个问题被问到/最后被回答以来,已经通过使用TextMarshalerTextUnmarshaler接口here添加了对JSON Marshal / UnMarshal映射的非字符串键类型的支持。您只需为您的键类型实现这些接口,然后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}]

答案 4 :(得分:0)

随着时间的推移,这种行为已经改变。我正在使用 go v1.16.5,我可以很高兴地将 int 类型作为 JSON 键传入。我现在已经尝试过同样的问题,我可以看到以下结果。 textMarshalertextUnmarshaler 接口添加了非字符串键的类型转换。有关详细信息,您可以访问此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}]