将Go地图转换为json

Cro*_*s87 77 json go

我试图将我的Go地图转换为带有encoding/jsonMarshal 的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)
}
Run Code Online (Sandbox Code Playgroud)

我的输出是:

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}]

[]
Run Code Online (Sandbox Code Playgroud)

我真的不知道我哪里错了.谢谢您的帮助.

jul*_*enc 82

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

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

// [] json: unsupported type: map[int]main.Foo
Run Code Online (Sandbox Code Playgroud)

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

有关更多详细信息,请参阅此帖子:https://stackoverflow.com/a/24284721/2679935

  • 在这里,您可以看到类型如何映射:http://golang.org/pkg/encoding/json/#Unmarshal您可以使用切片,它将映射到JSON数组.另外:总是检查错误;) (2认同)
  • 我想行为已经改变了。请参阅 https://golang.org/pkg/encoding/json/#Unmarshal,了解“地图的键类型必须是字符串、整数类型或实现 encoding.TextMarshaler”。 (2认同)

One*_*One 25

它实际上告诉你什么是错的,但你忽略了它,因为你没有检查从中返回的错误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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

playground

  • 你是对的.这是一个可耻的错误...我真的不知道为什么我用一个int作为json密钥...谢谢你的例子. (4认同)

vim*_*vim 5

自从提出/上次回答这个问题以来,已通过使用此处的TextMarshalerTextUnmarshaler接口添加了对 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)
}

Run Code Online (Sandbox Code Playgroud)

输出:

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}]
Run Code Online (Sandbox Code Playgroud)


kam*_*mal 5

随着时间的推移,这种行为已经发生了改变。我正在使用 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)
Run Code Online (Sandbox Code Playgroud)

输出:

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}]
Run Code Online (Sandbox Code Playgroud)