Goマップをjsonに変換


94

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

私の出力は:

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

[]

私はどこが間違っているのか本当にわかりません。ご協力ありがとうございました。


30
コメントせずに投票しないでください。質問は良い質問だと思います(+1):すべてのコードが含まれ、正確な質問、出力が含まれます...それは完全にトピックであり、OPは良い質問をするために多くの努力をしました。ここに反対投票があるのは本当に残念です!
topskip 2014

4
問題は、OPが質問にすぐに答えたであろうエラーを明示的に無視するという事実から生じます。
JimB 2014

3
私は間違いなく良心的でした。1つの質問に2つのエラー。あなたは私がそれらを繰り返さないことを確信することができます。
Cronos87 14

回答:


110

エラーが発生した場合は、次のようになります。

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
行動が変わったと思います。「マップのキータイプは文字列、整数タイプであるか、encoding.TextMarshalerを実装する必要があります」については、golang.org / pkg / encoding / json /#Unmarshalをご覧ください。
Ashhar Hasan

@AshharHasanどうやらGo 1.7(golang.org/doc/go1.7#encoding_json)で変更されたようですが、それでも期待どおりに動作しません:play.golang.org/p/0aFaQ_ByOk
julienc

sync.Mapでこれを行う方法はありますか?
Shahrukh Mohammad

@ShahrukhMohammad私は何年もGoを使用していません。あなたの質問に答えることができません...多分SOで新しい質問を作成してみてください!
julienc

27

実際には何が問題なのかがわかりますが、から返されたエラーを確認しなかったため無視しましたjson.Marshal

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

JSON仕様は、オブジェクトキーの文字列以外は何もサポートしていませんが、JavaScriptはそれについて煩雑ではありませんが、それでも違法です。

次の2つのオプションがあります。

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


4
あなたが正しい。恥ずかしいエラーです... jsonキーにintを使用した理由がよくわかりません...例をありがとうございます。
Cronos87 2014

2

この質問が最後に回答されたため、TextMarshalerおよびTextUnmarshalerインターフェースを使用して、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}]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.