แปลง Go map เป็น json


100

ฉันพยายามแปลงแผนที่ Go ของฉันเป็นสตริง json ด้วยencoding/jsonMarshal แต่ส่งผลให้สตริงว่างเปล่า

นี่คือรหัสของฉัน:

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

[]

ฉันไม่รู้จริงๆว่าฉันผิดตรงไหน ขอขอบคุณสำหรับความช่วยเหลือของคุณ.


32
โปรดอย่าลงคะแนนโดยไม่แสดงความคิดเห็น ฉันคิดว่าคำถามเป็นคำถามที่ดี (+1): มันมีรหัสทั้งหมดมีคำถามที่แม่นยำผลลัพธ์ ... มันอยู่ในหัวข้อโดยสิ้นเชิงและ OP ได้พยายามอย่างมากที่จะถามคำถามที่ดี เป็นเรื่องน่าเสียดายจริงๆที่ได้รับการโหวตที่นี่!
topskip

4
ปัญหาเกิดจากข้อเท็จจริงที่ว่า OP เพิกเฉยต่อข้อผิดพลาดที่จะตอบคำถามทันที
JimB

3
ฉันเข้าใจผิดอย่างชัดเจนว่าฉันคิดผิด สองข้อผิดพลาดในหนึ่งคำถาม คุณสามารถมั่นใจได้ว่าฉันจะไม่ทำซ้ำ
Cronos87

คำตอบ:


116

หากคุณพบข้อผิดพลาดคุณจะเห็นสิ่งนี้:

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

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

สิ่งนี้คือคุณไม่สามารถใช้จำนวนเต็มเป็นคีย์ใน JSON ได้ เป็นสิ่งต้องห้าม แต่คุณสามารถแปลงค่าเหล่านี้เป็นสตริงล่วงหน้าได้เช่นใช้strconv.Itoaไฟล์.

ดูรายละเอียดเพิ่มเติมในโพสต์นี้: https://stackoverflow.com/a/24284721/2679935


3
ที่นี่คุณสามารถดูวิธีการแมปประเภท: golang.org/pkg/encoding/json/#Unmarshal คุณสามารถใช้สไลซ์แทนซึ่งจะแมปกับอาร์เรย์ JSON นอกจากนี้: ตรวจสอบข้อผิดพลาดเสมอ;)
seong

2
ฉันเดาว่าพฤติกรรมเปลี่ยนไป ดูgolang.org/pkg/encoding/json/#Unmarshalสำหรับ "ประเภทคีย์ของแผนที่ต้องเป็นสตริงประเภทจำนวนเต็มหรือใช้การเข้ารหัส TextMarshaler"
Ashhar Hasan

@AshharHasan เห็นได้ชัดว่ามีการเปลี่ยนแปลงใน Go 1.7 ( golang.org/doc/go1.7#encoding_json ) แต่ก็ยังไม่เป็นไปตามที่คุณคาดหวัง: play.golang.org/p/0aFaQ_ByOk
กรกฎาคม

มีวิธีทำอย่างไรกับการซิงค์แผนที่?
Shahrukh Mohammad

@ShahrukhMohammad ฉันไม่ได้ใช้ Go มาหลายปีแล้วฉันจะไม่สามารถตอบคำถามของคุณได้ ... อาจจะลองสร้างคำถามใหม่ใน SO!
julienc

27

มันจริงจะบอกคุณว่ามีอะไรผิด json.Marshalแต่คุณไม่สนใจเพราะคุณไม่ได้ตรวจสอบข้อผิดพลาดกลับมาจาก

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

ข้อมูลจำเพาะ JSON ไม่รองรับอะไรเลยยกเว้นสตริงสำหรับอ็อบเจ็กต์คีย์ในขณะที่จาวาสคริปต์จะไม่ยุ่งเกี่ยวกับเรื่องนี้ แต่ก็ยังผิดกฎหมาย

คุณมีสองทางเลือก:

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 เพียงแค่ใช้ slice (อาร์เรย์จาวาสคริปต์):

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
คุณถูก. เป็นข้อผิดพลาดที่น่าเสียดาย ... ฉันไม่รู้จริงๆว่าทำไมฉันถึงใช้ int สำหรับคีย์ json ... ขอบคุณสำหรับตัวอย่างของคุณ
Cronos87

2

เนื่องจากคำถามนี้ถูกถาม / ตอบสุดท้าย, การสนับสนุนสำหรับประเภทหลักสตริงไม่ใช่สำหรับแผนที่สำหรับ JSON จอมพล / UnMarshal ได้รับการเพิ่มผ่านการใช้TextMarshalerและTextUnmarshalerอินเตอร์เฟซที่นี่ คุณสามารถใช้อินเทอร์เฟซเหล่านี้สำหรับประเภทคีย์ของคุณจากนั้น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}]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.