Ce qui se passe
Le 4 novembre 2026, l'équipe Go annonce que encoding/json/v2 et encoding/json/jsontext sont stables et
disponibles dans Go 1.27. C'est l'aboutissement de l'API expérimentale présentée l'an dernier, pour corriger
encoding/json, qui a plus de quinze ans. L'ancien paquet (v1) reste soumis à la promesse de compatibilité de Go 1 :
il est supporté indéfiniment, et personne n'est obligé de migrer.
Ce que v1 faisait de travers
- Il accepte l'UTF-8 invalide, alors que la RFC 8259 l'exige valide : corruption silencieuse de données.
- Il accepte les objets à noms dupliqués, sans signification universelle : une ambiguïté déjà exploitée contre des applications de sécurité (l'équipe cite CVE-2017-12635).
- Il marshale une slice ou une map
nilennull, ce qui fait échouer des décodeurs d'autres langages. - Il apparie les champs sans tenir compte de la casse : surprenant, potentiellement dangereux et lent.
- Décoder depuis un
io.Readeravecjson.NewDecoder(r).Decode(v)ne rejette pas les déchets à la fin. - Les options existent sur
EncoderetDecodermais pas surMarshal, ni dans les méthodesMarshalJSON.
Ce qui change dans v2
L'architecture sépare la syntaxe, dans jsontext (encodeur et décodeur en flux, sans réflexion), et le sens,
dans json/v2. Les options deviennent un argument de chaque appel :
out, err := json.Marshal(in, opts...)
err = json.UnmarshalRead(r, &v) // lit directement un io.Reader
err = json.MarshalWrite(w, in) // écrit directement dans un io.WriterLes défauts, plus stricts :
- erreur sur l'UTF-8 invalide et sur les noms dupliqués ;
- une slice ou une map
nildevient[]ou{}; - correspondance des champs sensible à la casse ;
omitemptyomet tout ce qui s'encode « vide » :null,"",[],{};- erreur sur
time.Duration, sans représentation par défaut ; l'appelant choisit par une option.
La plupart de ces comportements se règlent par une option ou une balise pour retrouver la sémantique de v1. Les
interfaces MarshalerTo et UnmarshalerFrom (méthodes MarshalJSONTo et UnmarshalJSONFrom) traitent le JSON en
flux et transmettent les options le long de la pile d'appels, ce que MarshalJSON et UnmarshalJSON ne permettaient pas.
Les chiffres, et les réserves
Marshal est à parité avec v1, parfois un peu plus rapide, parfois un peu plus lent. Unmarshal est nettement plus
rapide, jusqu'à 10 fois selon les bancs d'essai de l'équipe. Dans Kubernetes, passer à UnmarshalJSONFrom a
accéléré d'ordres de grandeur un service qui analysait des spécifications OpenAPI de façon récursive. Mais v2 n'est pas
un remplacement transparent : il y a des cas où il reste plus lent que v1, avec des améliorations annoncées pour Go 1.28.
Les deux versions sont compatibles : un paquet en v2 peut marshaler un type dont l'auteur a écrit un MarshalJSON de v1.
Comment s'y prendre
- Essayer v2 sur vos tests de contrat, pas sur la production.
- Chercher ce qui repose sur la tolérance de v1 : casse des champs,
nilennull, doublons, UTF-8 douteux. - Migrer vos
MarshalJSONetUnmarshalJSONcoûteux versMarshalJSONToetUnmarshalJSONFrom. - Lire la section « Migrating to v2 » de la documentation du paquet
encoding/json.
Source : le blog Go, via Hacker News. Source en anglais.