web-dev-qa-db-fra.com

Décodage JSON à l'aide de json.Unmarshal vs json.NewDecoder.Decode

Je développe un client API sur lequel je dois encoder une charge JSON à la demande et décoder un corps JSON à partir de la réponse.

J'ai lu le code source de plusieurs bibliothèques et, d'après ce que j'ai vu, j'ai deux possibilités pour coder et décoder une chaîne JSON.

Utilisez json.Unmarshal en passant la chaîne de réponse complète

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

ou en utilisant _json.NewDecoder.Decode_

_err = json.NewDecoder(resp.Body).Decode(value)
_

Dans mon cas, s’agissant de réponses HTTP implémentant _io.Reader_, la deuxième version semble nécessiter moins de code, mais depuis que j’ai vu les deux, je me demande s’il est préférable d’utiliser une solution plutôt que le autre.

De plus, la réponse acceptée de cette question dit

Veuillez utiliser _json.Decoder_ au lieu de _json.Unmarshal_.

mais il n'a pas mentionné la raison. Devrais-je vraiment éviter d'utiliser _json.Unmarshal_?

163
Simone Carletti

Cela dépend vraiment de votre contribution. Si vous examinez la mise en oeuvre de la méthode Decode de json.Decoder, elle met en mémoire tampon la valeur JSON entière en mémoire avant de la démultiplier dans une valeur Go. Ainsi, dans la plupart des cas, l’utilisation de la mémoire ne sera plus efficace (même si cela pourrait facilement changer dans une future version du langage).

Donc, une meilleure règle de base est la suivante:

  • Utilisez json.Decoder si vos données proviennent d’un flux io.Reader, ou si vous devez décoder plusieurs valeurs d’un flux de données.
  • Utilisez json.Unmarshal si vous avez déjà les données JSON en mémoire.

Pour le cas de la lecture d'une requête HTTP, je choisirais json.Decoder puisque vous lisiez à partir d'un flux.

195
James Henstridge