web-dev-qa-db-ja.com

json.Unmarshalとjson.NewDecoder.Decodeを使用してJSONをデコードする

要求時にJSONペイロードをエンコードし、応答からJSON本体をデコードする必要があるAPIクライアントを開発しています。

私はいくつかのライブラリからソースコードを読みましたが、私が見たものから、JSON文字列のエンコードとデコードには基本的に2つの可能性があります。

json.Unmarshal を使用して、応答文字列全体を渡します

data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
    err = json.Unmarshal(data, value)
}

またはjson.NewDecoder.Decodeを使用して

err = json.NewDecoder(resp.Body).Decode(value)

私の場合、io.Readerを実装するHTTP応答を処理するとき、2番目のバージョンは必要なコードが少ないようですが、両方を見たので、他のソリューションではなくソリューションを使用する必要があるかどうかが気になります。

さらに、 この質問から受け入れられた答え は言う

json.Decoderではなくjson.Unmarshalを使用してください。

しかし、それは理由に言及しませんでした。 json.Unmarshalの使用を本当に避けるべきですか?

163
Simone Carletti

それは本当にあなたの入力が何であるかに依存します。 json.DecoderDecodeメソッドの実装を見ると、Go値に非整列化する前に、JSON値全体をメモリにバッファリングします。そのため、ほとんどの場合、これ以上メモリ効率は良くなりません(ただし、これは将来のバージョンの言語では簡単に変更される可能性があります)。

したがって、より良い経験則は次のとおりです。

  • データがjson.Decoderストリームから来ている場合、またはデータのストリームから複数の値をデコードする必要がある場合は、io.Readerを使用します。
  • 既にJSONデータがメモリにある場合は、json.Unmarshalを使用します。

HTTPリクエストから読み取る場合、明らかにストリームから読み取るため、json.Decoderを選択します。

195