Konvertieren Sie die Go-Karte in json

93

Ich habe versucht, meine Go-Map mit encoding/jsonMarshal in eine JSON-Zeichenfolge zu konvertieren , aber es entstand eine leere Zeichenfolge.

Hier ist mein Code:

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

Meine Ausgabe ist:

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

[]

Ich weiß wirklich nicht, wo ich falsch liege. Danke für Ihre Hilfe.

Cronos87
quelle
29
Bitte stimmen Sie nicht ab, ohne einen Kommentar abzugeben. Ich denke, die Frage ist eine gute Frage (+1): Sie enthält den gesamten Code, eine genaue Frage, die Ausgabe, ... Sie ist völlig thematisch und das OP hat große Anstrengungen unternommen, um eine gute Frage zu stellen. Es ist wirklich eine Schande, die Downvotes hier zu haben!
Topskip
4
Das Problem ergibt sich aus der Tatsache, dass das OP den Fehler, der die Frage sofort beantwortet hätte, explizit ignoriert.
JimB
3
Ich bin eindeutig gewissenhaft, ich habe mich geirrt. Zwei Fehler in einer Frage. Sie können sicher sein, dass ich sie nicht wiederholen werde.
Cronos87

Antworten:

106

Wenn Sie den Fehler abgefangen hätten, hätten Sie Folgendes gesehen:

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

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

Die Sache ist, dass Sie in JSON keine Ganzzahlen als Schlüssel verwenden können. es ist verboten. Stattdessen können Sie diese Werte vorher in Zeichenfolgen konvertieren, z. B. mit strconv.Itoa.

Weitere Informationen finden Sie in diesem Beitrag: https://stackoverflow.com/a/24284721/2679935

julienc
quelle
3
Hier können Sie sehen, wie die Typen zugeordnet sind: golang.org/pkg/encoding/json/#Unmarshal Sie können stattdessen ein Slice verwenden, das einem JSON-Array zugeordnet wird. Auch: immer auf Fehler prüfen;)
Seong
2
Ich denke, das Verhalten hat sich geändert. Siehe golang.org/pkg/encoding/json/#Unmarshal für "Der Schlüsseltyp der Karte muss entweder eine Zeichenfolge oder ein ganzzahliger Typ sein oder encoding.TextMarshaler implementieren."
Ashhar Hasan
@AshharHasan Anscheinend hat es sich in Go 1.7 ( golang.org/doc/go1.7#encoding_json ) geändert , aber es macht immer noch nicht das, was Sie erwarten würden: play.golang.org/p/0aFaQ_ByOk
julienc
Gibt es eine Möglichkeit, dies mit einer sync.Map zu tun?
Shahrukh Mohammad
@ShahrukhMohammad Ich habe Go seit Jahren nicht mehr verwendet, ich kann Ihre Frage nicht beantworten ... Vielleicht versuchen Sie, eine neue Frage zu SO zu erstellen!
Julienc
27

Es sagt Ihnen tatsächlich, was falsch ist, aber Sie haben es ignoriert, weil Sie den zurückgegebenen Fehler nicht überprüft haben json.Marshal.

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

Die JSON-Spezifikation unterstützt nichts außer Zeichenfolgen für Objektschlüssel, während Javascript nicht pingelig ist, es ist immer noch illegal.

Sie haben zwei Möglichkeiten:

1 Verwenden Sie map[string]Fooden Index und konvertieren Sie ihn in einen String (z. B. mit 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 Verwenden Sie einfach ein Slice (Javascript-Array):

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

OneOfOne
quelle
4
Du hast recht. Es ist ein beschämender Fehler ... Ich weiß nicht wirklich, warum ich ein int für einen json-Schlüssel verwendet habe ... Vielen Dank für Ihre Beispiele.
Cronos87
2

Da diese Frage gestellt / zuletzt beantwortet wurde, wurde die Unterstützung für Nicht-String-Schlüsseltypen für Karten für json Marshal / UnMarshal durch die Verwendung der TextMarshaler- und TextUnmarshaler- Schnittstellen hier hinzugefügt . Sie könnten diese Schnittstellen einfach für Ihre Schlüsseltypen implementieren und dann json.Marshalwie erwartet funktionieren.

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

Ausgabe:

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