Chuyển đổi bản đồ Go sang json


94

Tôi đã cố gắng chuyển đổi bản đồ cờ vây của mình thành một chuỗi json với encoding/jsonMarshal, nhưng nó dẫn đến một chuỗi trống.

Đây là mã của tôi:

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

Đầu ra của tôi là:

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

[]

Tôi thực sự không biết mình sai ở đâu. Cảm ơn sự giúp đỡ của bạn.


30
Vui lòng không downvote mà không đưa ra nhận xét. Tôi nghĩ câu hỏi là một câu hỏi hay (+1): nó chứa tất cả mã, nó chứa một câu hỏi chính xác, kết quả, ... Nó hoàn toàn có chủ đề và OP đã nỗ lực rất nhiều để đưa ra một câu hỏi hay. Thực sự rất tiếc khi có những phiếu phản đối ở đây!
Topkip

4
Vấn đề xuất phát từ thực tế là OP đã bỏ qua một cách rõ ràng lỗi mà lẽ ra đã trả lời câu hỏi một cách không chính xác.
JimB

3
Tôi rõ ràng là tận tâm, tôi đã sai. Hai lỗi trong một câu hỏi. Bạn có thể chắc chắn rằng tôi sẽ không lặp lại chúng.
Cronos87

Câu trả lời:


110

Nếu bạn gặp lỗi, bạn sẽ thấy điều này:

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

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

Vấn đề là bạn không thể sử dụng số nguyên làm khóa trong JSON; nó bị cấm. Thay vào đó, bạn có thể chuyển đổi trước các giá trị này thành chuỗi, chẳng hạn bằng cách sử dụng strconv.Itoa.

Xem bài đăng này để biết thêm chi tiết: https://stackoverflow.com/a/24284721/2679935


3
Tại đây, bạn có thể thấy cách các loại ánh xạ: golang.org/pkg/encoding/json/#Unmarshal Thay vào đó, bạn có thể sử dụng một lát cắt, lát này sẽ ánh xạ tới một mảng JSON. Ngoài ra: luôn kiểm tra lỗi;)
seong

2
Tôi đoán hành vi đã thay đổi. Xem golang.org/pkg/encoding/json/#Unmarshal để biết "Loại khóa của bản đồ phải là chuỗi, kiểu số nguyên hoặc triển khai mã hóa.TextMarshaler."
Ashhar Hasan

@AshharHasan Rõ ràng nó đã thay đổi tại Gò 1,7 ( golang.org/doc/go1.7#encoding_json ), nhưng nó vẫn không làm những gì bạn mong đợi: play.golang.org/p/0aFaQ_ByOk
julienc

có cách nào để thực hiện việc này với sync.Map không?
Shahrukh Mohammad

@ShahrukhMohammad Tôi đã không sử dụng Go trong nhiều năm, tôi sẽ không thể trả lời câu hỏi của bạn ... Có thể hãy thử tạo một câu hỏi mới trên SO!
julienc

27

Nó thực sự cho bạn biết điều gì sai, nhưng bạn đã bỏ qua nó vì bạn không kiểm tra lỗi được trả về từ đó json.Marshal.

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

Đặc tả JSON không hỗ trợ bất kỳ thứ gì ngoại trừ các chuỗi cho các khóa đối tượng, trong khi javascript sẽ không gây chú ý về nó, nó vẫn là bất hợp pháp.

Bạn có hai lựa chọn:

1 Sử dụng map[string]Foovà chuyển đổi chỉ mục thành chuỗi (ví dụ: sử dụng 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 Đơn giản chỉ cần sử dụng một lát (mảng 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


4
Bạn đúng. Đó là một lỗi đáng xấu hổ ... Tôi thực sự không biết tại sao tôi lại sử dụng int cho khóa json ... Cảm ơn bạn đã cho ví dụ của bạn.
Cronos87

2

Kể từ khi câu hỏi này được hỏi / trả lời cuối cùng, hỗ trợ với nhiều loại phi chính chuỗi cho bản đồ cho json Marshal / unmarshal đã được thêm vào thông qua việc sử dụng các TextMarshalerTextUnmarshaler giao diện ở đây . Bạn chỉ có thể triển khai các giao diện này cho các loại khóa của mình và sau đó json.Marshalsẽ hoạt động như mong đợi.

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

Đầu ra:

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}]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.