Travailler avec JSON en Go necessite la definition de types struct qui correspondent a votre structure JSON. Ce guide couvre le mapping de types, les structures imbriquees, les champs optionnels et les bonnes pratiques.
Convertissez JSON en structs Go avec notre outil gratuit.
Bases du mapping de types JSON vers Go
Chaque type JSON a un type Go correspondant.
JSON Type Go Type Example
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
string string "hello" â "hello"
number (integer) int / int64 42 â 42
number (float) float64 3.14 â 3.14
boolean bool true â true
null *T (pointer) null â nil
object struct {...} â MyStruct{}
array of strings []string ["a","b"] â []string{"a","b"}
array of objects []MyStruct [{...}] â []MyStruct{...}
array of mixed []interface{} [1,"a",true] â []interface{}{...}
dynamic object map[string]any {...} â map[string]any{...}Pour les valeurs null, utilisez des types pointeurs (*string, *int).
Tags de struct JSON : Guide essentiel
Les tags indiquent au package encoding/json comment mapper les cles JSON aux champs.
package main
import (
"encoding/json"
"fmt"
)
// Basic struct with json tags
type User struct {
// Field name â json key mapping
ID int `json:"id"` // "id" in JSON
FirstName string `json:"first_name"` // "first_name" in JSON
LastName string `json:"last_name"` // "last_name" in JSON
Email string `json:"email"` // "email" in JSON
Age int `json:"age,omitempty"` // skip if zero value
Password string `json:"-"` // always skip (never serialize)
// Without tag - uses field name as-is (case-insensitive unmarshal)
Username string // matches "Username", "username", etc.
}
func main() {
jsonData := `{
"id": 1,
"first_name": "Alice",
"last_name": "Smith",
"email": "alice@example.com",
"age": 0,
"Username": "alice123"
}`
var user User
if err := json.Unmarshal([]byte(jsonData), &user); err != nil {
panic(err)
}
fmt.Printf("Name: %s %s\n", user.FirstName, user.LastName)
// Output: Name: Alice Smith
// Marshal back - age is omitted because it's 0 (omitempty)
output, _ := json.MarshalIndent(user, "", " ")
fmt.Println(string(output))
}Les champs doivent etre exportes (majuscule) pour etre visibles par le package JSON.
Objets JSON imbriques
Les objets imbriques necessitent des definitions de struct separees.
// JSON input:
// {
// "id": 1,
// "name": "Acme Corp",
// "address": {
// "street": "123 Main St",
// "city": "Springfield",
// "state": "IL",
// "zip": "62701",
// "coordinates": {
// "lat": 39.7817,
// "lng": -89.6501
// }
// },
// "contacts": [
// { "name": "Alice", "role": "CEO", "email": "alice@acme.com" },
// { "name": "Bob", "role": "CTO", "email": "bob@acme.com" }
// ]
// }
// Define separate structs for each nested level
type Coordinates struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
type Address struct {
Street string `json:"street"`
City string `json:"city"`
State string `json:"state"`
Zip string `json:"zip"`
Coordinates Coordinates `json:"coordinates"`
}
type Contact struct {
Name string `json:"name"`
Role string `json:"role"`
Email string `json:"email"`
}
type Company struct {
ID int `json:"id"`
Name string `json:"name"`
Address Address `json:"address"`
Contacts []Contact `json:"contacts"`
}Definissez chaque type de struct separement pour la lisibilite et la reutilisation.
Tableaux et slices
Les tableaux JSON correspondent aux slices Go.
// Different array types in JSON â Go
type Product struct {
Name string `json:"name"`
Tags []string `json:"tags"` // ["electronics", "sale"]
Prices []float64 `json:"prices"` // [29.99, 39.99, 49.99]
Ratings []int `json:"ratings"` // [5, 4, 5, 3]
IsActive []bool `json:"flags"` // [true, false, true]
// Array of objects
Reviews []Review `json:"reviews"`
// Nested array of arrays (matrix)
Matrix [][]int `json:"matrix"` // [[1,2],[3,4]]
// Mixed-type array (rare but possible)
Metadata []interface{} `json:"metadata"` // [1, "hello", true]
}
type Review struct {
Author string `json:"author"`
Rating int `json:"rating"`
Comment string `json:"comment"`
}
// Empty arrays vs null arrays
type Response struct {
// null in JSON â nil slice (len=0, cap=0, == nil)
// [] in JSON â empty slice (len=0, cap=0, != nil)
// omitempty skips nil slices but NOT empty slices
Items []Item `json:"items,omitempty"`
}Champs optionnels et nullables
Go a trois patterns pour les champs optionnels :
// Pattern 1: omitempty - skip zero values when marshaling
type UpdateRequest struct {
Name string `json:"name,omitempty"` // "" is skipped
Age int `json:"age,omitempty"` // 0 is skipped
Admin bool `json:"admin,omitempty"` // false is skipped
}
// Problem: Can't distinguish "age not provided" from "age is 0"
// Pattern 2: Pointer types - distinguish null/missing from zero
type UpdateRequestV2 struct {
Name *string `json:"name,omitempty"` // nil = not provided, "" = empty
Age *int `json:"age,omitempty"` // nil = not provided, 0 = zero
Admin *bool `json:"admin,omitempty"` // nil = not provided, false = false
}
// Helper function to create pointers (Go doesn't allow &literal)
func ptr[T any](v T) *T { return &v }
// Usage:
// req := UpdateRequestV2{
// Name: ptr("Alice"),
// Age: ptr(0), // explicitly set to 0, not nil
// }
// Pattern 3: json.RawMessage - defer parsing
type Event struct {
Type string `json:"type"`
Payload json.RawMessage `json:"payload"` // raw JSON bytes
}
// Parse payload based on type
func (e *Event) ParsePayload() (interface{}, error) {
switch e.Type {
case "user_created":
var u User
return &u, json.Unmarshal(e.Payload, &u)
case "order_placed":
var o Order
return &o, json.Unmarshal(e.Payload, &o)
default:
var m map[string]interface{}
return &m, json.Unmarshal(e.Payload, &m)
}
}Choisissez le pattern adapte : omitempty pour les valeurs zero acceptables, pointeurs pour distinguer "non fourni" et "valeur zero".
Marshaling JSON personnalise
Implementez json.Marshaler et json.Unmarshaler pour une logique personnalisee.
import (
"encoding/json"
"time"
"fmt"
"strings"
)
// Custom date format (JSON uses "2006-01-02", not RFC3339)
type Date struct {
time.Time
}
const dateFormat = "2006-01-02"
func (d *Date) UnmarshalJSON(data []byte) error {
// Remove quotes from JSON string
s := strings.Trim(string(data), `"`)
if s == "null" || s == "" {
return nil
}
t, err := time.Parse(dateFormat, s)
if err != nil {
return fmt.Errorf("invalid date format: %s", s)
}
d.Time = t
return nil
}
func (d Date) MarshalJSON() ([]byte, error) {
if d.Time.IsZero() {
return []byte("null"), nil
}
return json.Marshal(d.Time.Format(dateFormat))
}
// Usage in a struct
type Employee struct {
Name string `json:"name"`
StartDate Date `json:"start_date"`
EndDate *Date `json:"end_date,omitempty"`
}
// Custom enum type
type Status string
const (
StatusActive Status = "active"
StatusInactive Status = "inactive"
StatusPending Status = "pending"
)
func (s *Status) UnmarshalJSON(data []byte) error {
var str string
if err := json.Unmarshal(data, &str); err != nil {
return err
}
switch Status(str) {
case StatusActive, StatusInactive, StatusPending:
*s = Status(str)
return nil
default:
return fmt.Errorf("invalid status: %s", str)
}
}Cas courants : formats de date, conversion de types, enums, aplatissement de structures.
Patterns API reels
Patterns JSON courants avec les APIs REST et leur modelisation en Go.
// Pattern: Paginated API Response
type PaginatedResponse[T any] struct {
Data []T `json:"data"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
TotalPages int `json:"total_pages"`
NextURL string `json:"next_url,omitempty"`
PrevURL string `json:"prev_url,omitempty"`
}
// Pattern: API Error Response
type APIError struct {
Code int `json:"code"`
Message string `json:"message"`
Details map[string]string `json:"details,omitempty"`
}
func (e *APIError) Error() string {
return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}
// Pattern: Wrapper for success/error responses
type APIResponse[T any] struct {
Success bool `json:"success"`
Data *T `json:"data,omitempty"`
Error *APIError `json:"error,omitempty"`
}
// Pattern: Webhook payload with dynamic event data
type WebhookPayload struct {
ID string `json:"id"`
Event string `json:"event"`
Timestamp time.Time `json:"timestamp"`
Data json.RawMessage `json:"data"`
}
// Pattern: Configuration file with defaults
type Config struct {
Host string `json:"host"`
Port int `json:"port"`
Debug bool `json:"debug"`
LogLevel string `json:"log_level"`
Database struct {
URL string `json:"url"`
MaxConnections int `json:"max_connections"`
ConnectTimeout int `json:"connect_timeout_ms"`
} `json:"database"`
}
// Set defaults before unmarshaling
func NewConfig() *Config {
return &Config{
Host: "localhost",
Port: 8080,
LogLevel: "info",
}
}
func LoadConfig(data []byte) (*Config, error) {
cfg := NewConfig()
if err := json.Unmarshal(data, cfg); err != nil {
return nil, err
}
return cfg, nil
}Generation automatique de structs
Notre outil JSON to Go genere automatiquement des definitions de struct correctement taguees.
Convertissez JSON en structs Go avec notre outil gratuit.
Pour CI/CD, utilisez json-to-go en ligne de commande ou go-jsonschema.
# Generate Go structs from a JSON file
cat api-response.json | json-to-go
# Generate from a JSON Schema definition
go install github.com/atombender/go-jsonschema/cmd/gojsonschema@latest
gojsonschema -p models schema.json
# Validate your structs handle the JSON correctly
go test -run TestUnmarshal ./models/...Questions frequentes
Comment convertir JSON en struct Go ?
Definissez un struct avec des champs exportes et des tags json. Utilisez notre outil en ligne.
Qu'est-ce que omitempty en Go ?
omitempty saute les champs a valeur zero lors du marshaling. Utile pour les requetes PATCH.
Comment gerer les valeurs null ?
Utilisez des types pointeurs (*string, *int, *bool). Le pointeur sera nil quand JSON est null.
Peut-on avoir des noms JSON differents ?
Oui, avec les tags de struct : `json:"user_name"` mappe la cle JSON au champ Go.
Comment gerer les champs JSON dynamiques ?
map[string]interface{} pour du JSON dynamique, json.RawMessage pour le parsing differe.
Convertir JSON en structs Go correctement est fondamental. Utilisez notre outil en ligne ou etablissez des conventions de tags coherentes.
Essayez le convertisseur JSON to Go.
Related Developer Tools and Guides
- JSON to Go Converter - Generate Go struct definitions from JSON data instantly
- JSON Formatter - Format and validate JSON before conversion
- JSON to TypeScript - Generate TypeScript interfaces from JSON
- JSON Validator - Validate your JSON structure before generating structs
- JSON to Go Struct Best Practices - Struct tag patterns and mapping strategies
- JSON vs YAML vs TOML - Compare data serialization formats
- REST API Best Practices - Design robust APIs with proper JSON structures
- Protobuf vs JSON - When to use Protocol Buffers over JSON