Convertisseur JSON → struct Go, gratuit

Analysez du JSON et générez automatiquement des définitions de struct Go avec noms de champs en PascalCase et balises json pour une intégration fluide dans votre code Go.

Entrée & sortie

Options

Comment ça marche

  1. Collez votre JSON : saisissez n'importe quel objet JSON ou structure imbriquée dans le champ d'entrée.
  2. Obtenez la struct Go : la définition équivalente de struct Go avec des noms de champs, types et balises JSON corrects est générée instantanément.
  3. Copiez et utilisez : copiez le code de la struct et collez-le dans votre projet Go pour commencer à désérialiser des données JSON.

Pourquoi utiliser le convertisseur JSON → struct Go ?

Écrire des structs Go à la main pour des réponses JSON complexes est fastidieux et sujet aux erreurs, surtout quand l'API renvoie des objets profondément imbriqués avec des dizaines de champs. JSON → Go automatise cela en analysant la forme du JSON et en générant des structs Go correctement typées avec des balises json:"…" appropriées, correspondant aux noms de champs JSON. Cela accélère le développement Go lors de la consommation d'API REST, du traitement de charges utiles webhook ou du travail avec toute source de données JSON.

Fonctionnalités

  • Génération de structs imbriquées : les objets JSON profondément imbriqués sont convertis en définitions de structs Go imbriquées.
  • Inférence de types : chaînes, nombres, booléens, tableaux et valeurs null sont associés aux types Go appropriés.
  • Balises JSON : tous les champs incluent des balises de struct json:"fieldName" correspondant aux clés JSON d'origine.
  • Gestion des tableaux : les tableaux JSON deviennent des slices Go avec le bon type d'éléments.
  • Types pointeurs : les champs JSON nullables sont représentés par des types pointeurs (par exemple, *string).

Questions fréquentes

Comment sont gérées les valeurs null ?

Les champs JSON null sont convertis en types pointeurs en Go (par exemple, *string, *int), ce qui permet de représenter à la fois nil et une valeur réelle. Cela gère correctement les champs optionnels ou nullables dans la réponse d'API.

Et si le JSON a des types incohérents ?

Si le même champ apparaît avec des types différents entre les objets JSON (fréquent dans les API réelles), le convertisseur peut inférer interface{} (any dans le Go moderne). Relisez ces champs et ajoutez des assertions de types personnalisées au besoin.

Génère-t-il le code de désérialisation complet ?

L'outil génère les définitions de structs. Pour désérialiser, utilisez json.Unmarshal(data, &myStruct) ou json.NewDecoder(r.Body).Decode(&myStruct) avec le package encoding/json standard.

Brève histoire de Go et JSON

Go a été annoncé chez Google par Rob Pike, Robert Griesemer et Ken Thompson en novembre 2009 ; le paquet encoding/json a atterri dans la bibliothèque standard avant Go 1.0 (mars 2012). Le parsing JSON en Go est basé sur la réflexion : vous déclarez une struct, taguez les champs avec json:"name", et json.Unmarshal parcourt à la fois la struct et les octets. Le motif s'est révélé si productif que l'écriture manuelle de structs pour de grandes APIs est devenue rapidement fastidieuse. Mat Ryer a construit mholt/json-to-go comme un outil uniquement JavaScript en 2014 (il est encore maintenu à mholt.github.io/json-to-go) en utilisant l'analyse JSON basée sur regex dans le navigateur. quicktype (David Siegel, 2017) a généralisé l'idée à 23 langages dont TypeScript, Rust, Swift, Kotlin, Python, Java. easyjson axé sur les performances (Mail.ru, 2016) saute la réflexion en générant du code de marshalling au moment de la compilation, 4-5× plus rapide que encoding/json pour les chemins chauds. Go 1.18 (mars 2022) a ajouté les génériques, ce qui a simplifié certains helpers de marshalling mais n'a pas changé l'idiome des tags de struct. Go 1.21 (août 2023) a ajouté le paquet expérimental encoding/json/v2 (proposition encore en discussion en 2024), visant à corriger les pièges de longue date comme les incompatibilités de types silencieuses et la réflexion lente.

Struct vs map[string]interface{} : quand chacun a du sens

  • Les structs typées gagnent pour les formes connues. Si vous contrôlez l'API ou avez un schéma stable, les structs vous donnent une vérification de champs à la compilation, l'autocomplétion de l'IDE et un parsing 2-3× plus rapide. json.Unmarshal dans une struct ne touche que les champs qu'il reconnaît, ignorant silencieusement les clés JSON inconnues (sauf si vous appelez decoder.DisallowUnknownFields).
  • Les maps gagnent pour le JSON arbitraire. map[string]interface{} (ou en Go 1.18+ map[string]any) gère des formes très variables, payloads webhook de nombreuses sources, configurations de plugins, documents MongoDB. Compromis : chaque accès nécessite une assertion de type (data["age"].(float64)), et les nombres se parsent en float64 par défaut, perdant en précision pour les grands entiers.
  • Hybride : champs connus en struct, inconnus en map. Utilisez json.RawMessage pour différer le parsing ou ajoutez un champ catch-all Extra map[string]interface{} `json:"-,inline"` (avec l'aide de bibliothèques comme go-restful). Les SDK Go de Stripe et Twilio utilisent ce motif pour des réponses API à compatibilité ascendante.
  • Écart de performance. Les chemins chauds (par exemple parser 10 000 événements webhook par seconde) bénéficient des marshallers générés : easyjson, ffjson, go-json, sonic (ByteDance, 2022, utilise JIT pour générer du code machine à l'exécution, la bibliothèque JSON la plus rapide en Go). Le parsing générique basé sur struct gère peut-être 100-200 Mo/s ; sonic gère 1-2 Go/s.
  • Streaming pour gros JSON. Un fichier JSON de 1 Go ne tient pas en mémoire. json.Decoder.Token() lit token par token. json.Decoder.More() parcourt les éléments de tableau un à la fois. Utilisez le streaming pour les fichiers journaux, les grands datasets, les flux ND-JSON (un objet JSON par ligne, utilisé par OpenSearch, BigQuery, l'API ChatGPT).

Où la conversion JSON vers Go fait gagner du temps réel

  • Intégration d'API REST. Stripe, GitHub, Slack, Notion retournent tous du JSON profondément imbriqué. Prendre une réponse d'exemple et la coller dans json-to-go produit 80-90 % de la struct finale. Dépensez le temps économisé sur les 10 % (unmarshallers personnalisés pour les formats de temps, sémantique omitempty, champs pointeurs optionnels).
  • Gestionnaires de webhooks. Un payload webhook Stripe typique fait 80-200 champs avec 3-5 niveaux d'imbrication. Taper à la main la struct Go prend 30-60 minutes ; coller le payload d'exemple via json-to-go prend 30 secondes.
  • Parsing de configuration. Les fichiers de configuration JSON (préférés au TOML par AWS Lambda, Docker Compose compose.json, devcontainer.json) se mappent proprement aux structs Go. encoding/json gère à la fois la lecture et l'écriture du fichier avec la même struct.
  • Ponts gRPC et Protobuf. Les types Go protobuf générés incluent les tags json. Lors du transcodage entre protobuf et JSON (gRPC-Gateway, Buf, Connect), json-to-go aide à esquisser le côté Go à partir du format wire JSON.
  • Colonnes JSONB de base de données. PostgreSQL jsonb, documents MongoDB, colonnes JSON MySQL. Le driver database/sql retourne []byte que vous unmarshalez en struct. Les générateurs accélèrent le premier passage pour les tables schema-on-read.
  • Données fixture pour les tests. Une vraie réponse JSON de production devient la fixture de test. json-to-go vous donne la struct dans laquelle unmarshaler pour les assertions. Combiné avec les répertoires testdata/ (convention Go depuis 1.10), garde les tests proches de la réalité.
  • Pipelines CSV-vers-JSON-vers-struct. Pour les tâches d'ingénierie de données : lire le CSV, marshaler en JSON pour inspection, coller dans json-to-go pour obtenir la struct, puis écrire un pipeline typé. Bien plus rapide que de deviner les types de colonnes depuis un tableur.

Erreurs courantes après génération de structs

  • Oublier la gestion de time.Time. encoding/json suppose le format RFC 3339 (2026-05-13T12:34:56Z). La plupart des APIs livrent ceci mais certaines utilisent les timestamps Unix (Stripe), ISO sans fuseau horaire (anciennes APIs Microsoft), ou des chaînes personnalisées. Pour non-RFC-3339, définissez un type personnalisé avec une méthode UnmarshalJSON.
  • Dépassement d'entier avec float64 par défaut. Un nombre JSON parsé en interface{} devient float64 ; les nombres au-dessus de 2^53 perdent en précision. Les IDs clients Stripe, snowflake Twitter, utilisateurs Discord (tous 64 bits) nécessitent json.Number ou int64 dans votre struct. Utilisez json.Decoder.UseNumber() pour un parsing sûr en interface{}.
  • Mauvaise compréhension d'omitempty. omitempty omet le champ au marshal si c'est la valeur zéro (chaîne vide, 0, pointeur nil, slice/map vide). Cela ne signifie pas «optionnel à l'unmarshal». Un champ int avec valeur 0 est indissociable d'un manquant ; utilisez *int si vous avez besoin de savoir si l'API a omis le champ ou envoyé zéro.
  • Incompatibilités de casse de noms de champs. Les champs Go doivent être exportés (capitalisés) pour être marshalés. Le nom JSON par défaut est le nom Go littéralement, donc UserID devient "UserID" en JSON sauf si tagué. Les générateurs ajoutent des tags json:"userId" pour faire le pont entre PascalCase de Go et camelCase de JSON. Oublier le tag signifie que votre code «fonctionne» avec lui-même mais échoue contre les APIs externes.
  • Sur-utilisation des types pointeurs. Les générateurs utilisent parfois *string ou *int par défaut pour la sécurité. Cela fait que chaque accès nécessite une vérification nil. Si l'API garantit que le champ est toujours présent (lisez la doc API), utilisez le type valeur et sautez l'indirection.
  • Types incohérents entre réponses. Certaines APIs retournent tags: []string{"foo"} dans une réponse et tags: "foo" comme chaîne dans une autre. La pure génération de code ne peut pas faire le pont. Écrivez un UnmarshalJSON personnalisé qui gère les deux cas, ou passez à interface{} et documentez la variabilité.
  • Suppression silencieuse de champs inconnus. Par défaut, json.Unmarshal ignore les clés JSON absentes de la struct. C'est souvent un bug : l'API a ajouté un champ, votre code ne le sait pas. Utilisez decoder.DisallowUnknownFields() dans les tests pour attraper les dérives ; en production gardez-le permissif.

Autres questions fréquemment posées

En quoi cela diffère-t-il du canonique mholt/json-to-go ?

Même algorithme de base : parser le JSON, inférer les types depuis la première occurrence de chaque champ, générer une struct avec des champs tagués entre backticks. Cette implémentation tourne entièrement dans votre navigateur sans analytics ni appels réseau ; la canonique est hébergée à mholt.github.io/json-to-go, aussi navigateur-seul mais sur un domaine différent. La sortie devrait correspondre pour ~95 % des entrées ; les cas limites (tableaux de types mixtes, structs anonymes profondément imbriquées) peuvent différer légèrement. Si vous avez besoin d'une sortie mholt exacte, utilisez celle-là ; si vous avez besoin de garanties de confidentialité que le JSON ne quitte jamais votre appareil, utilisez celui-ci.

Pourquoi certains champs sont-ils générés comme interface{} ?

Trois raisons habituelles. Premièrement, literal null dans le JSON source : le générateur ne peut pas inférer un type utile depuis null seul, donc il retombe sur interface{}. Remplacez par un pointeur typé (*string, *int) une fois que vous connaissez le vrai schéma. Deuxièmement, tableaux de types mixtes : [1, "two", true] ne peut pas être un slice typé. Troisièmement, champ entièrement manquant dans votre échantillon, collez un JSON plus représentatif si disponible. En Go 1.18+ vous pouvez remplacer interface{} par l'alias plus propre any ; ils sont identiques au niveau type.

Puis-je faire un aller-retour du JSON à travers cette struct sans perte de données ?

Généralement oui, avec des réserves. encoding/json préserve les valeurs des champs mais pas l'ordre des champs (la spec JSON dit que l'ordre des champs est non pertinent ; les maps Go sont délibérément aléatoires). Précision numérique : les int64s au-dessus de 2^53 font l'aller-retour sûrement en int64 Go, mais si vous castez à float64 ou passez par JavaScript (par exemple intermédiaire navigateur), vous perdez des chiffres. Les champs JSON inconnus sont silencieusement supprimés à l'unmarshal-puis-remarshal, préservez-les avec un catch-all map[string]json.RawMessage si la fidélité de l'aller-retour compte.

Quand devrais-je utiliser du code struct généré (easyjson, sonic) au lieu d'encoding/json ?

Par défaut, encoding/json: c'est suffisant pour 95 % des services et il livre avec le langage. Passez à easyjson ou sonic quand vous avez profilé et que le marshalling JSON apparaît dans votre flame graph CPU à >10 % du temps total. Points de bascule typiques : services HTTP gérant des milliers de requêtes par seconde, agrégateurs de logs ingérant des Go/heure, flux temps réel. Les deux alternatives gardent les mêmes définitions de struct et tags, donc vous pouvez les swapper sans changer les déclarations de champs.

Mon JSON est-il envoyé à un serveur ?

Non. Le parsing JSON et la génération de code Go tournent tous deux en JavaScript sur votre appareil. Ouvrez l'onglet Network dans DevTools pendant que vous collez ; vous verrez zéro requête sortante. Sûr pour les réponses d'API propriétaires, les fixtures de données clients, les payloads webhook avec PII, et tout ce qui est couvert par un NDA.