encoding/json.Marshal în Go

Transformă o valoare Go (structură, map, slice) în JSON compact; etichetele json:"..." aleg numele și regulile câmpurilor.

Sintaxă
import "encoding/json"

func Marshal(v any) ([]byte, error)

// etichete de structură:
type T struct {
    Camp  tip `json:"nume"`
    Camp2 tip `json:"nume,omitempty"`
    Camp3 tip `json:"nume,omitzero"`   // Go 1.24
    Camp4 tip `json:"-"`
    Camp5 int `json:"nume,string"`
}

Ce face encoding/json.Marshal

json.Marshal(v) returnează textul JSON al valorii v ca []byte (îl afișezi cu string(date)). Structurile devin obiecte, slice-urile și tablourile devin liste, map-urile cu chei text devin obiecte (cu cheile sortate), nil devine null, time.Time devine text RFC 3339. Doar câmpurile exportate (cu literă mare) ajung în JSON.

Etichetele de structură (struct tags) controlează fiecare câmp: `json:"nume"` schimbă numele cheii (în JSON se folosesc de obicei litere mici), `json:"-"` exclude câmpul (parole, date interne), `json:",omitempty"` omite câmpul când este gol ("", 0, false, nil, slice sau map gol), `json:",omitzero"` (Go 1.24) omite câmpul când are valoarea zero, inclusiv o structură sau un time.Time zero, iar `json:",string"` scrie un număr între ghilimele.

Eticheta se scrie între apostrofuri inverse după tipul câmpului, exact în forma json:"...", fără spații în jurul lui :. Opțiunile se separă prin virgulă după nume; dacă vrei doar opțiunea, lași numele gol (`json:",omitempty"`). go vet semnalează etichetele scrise greșit. Pentru JSON formatat frumos, folosește MarshalIndent.

Parametri

Parametru Descriere
v Valoarea de transformat: structură, pointer la structură, map, slice, număr, text etc.

Ce returnează

JSON-ul ca []byte și o eroare (de exemplu pentru canale, funcții sau valori NaN, care nu au echivalent JSON).

Exemple

Exemplul 1: Structură cu etichete JSON

Parola are -, deci nu apare. Telefon este gol și are omitempty, deci lipsește. varsta (literă mică) nu este exportat și este ignorat.

package main

import (
	"encoding/json"
	"fmt"
)

type Client struct {
	ID       int      `json:"id"`
	Nume     string   `json:"nume"`
	Email    string   `json:"email"`
	Telefon  string   `json:"telefon,omitempty"`
	Parola   string   `json:"-"`
	Etichete []string `json:"etichete"`
	Activ    bool     `json:"activ"`
	varsta   int
}

func main() {
	c := Client{
		ID:       7,
		Nume:     "Ana Popescu",
		Email:    "ana@example.ro",
		Parola:   "secret123",
		Etichete: []string{"vip", "newsletter"},
		Activ:    true,
		varsta:   31,
	}
	date, err := json.Marshal(c)
	if err != nil {
		fmt.Println("eroare:", err)
		return
	}
	fmt.Println(string(date))
}

Rezultat

{"id":7,"nume":"Ana Popescu","email":"ana@example.ro","etichete":["vip","newsletter"],"activ":true}

Exemplul 2: omitempty față de omitzero

omitempty nu omite structuri (un time.Time zero apare ca 0001-01-01...). omitzero omite orice valoare zero, inclusiv structuri.

package main

import (
	"encoding/json"
	"fmt"
	"time"
)

type Comanda struct {
	Numar     int       `json:"numar"`
	Reducere  float64   `json:"reducere,omitempty"`
	Note      []string  `json:"note,omitempty"`
	Livrata   time.Time `json:"livrata,omitempty"`
	Anulata   time.Time `json:"anulata,omitzero"`
	Cantitate int       `json:"cantitate,string"`
}

func main() {
	c := Comanda{Numar: 1001, Cantitate: 3}
	date, _ := json.Marshal(c)
	fmt.Println(string(date))

	c.Reducere = 10.5
	c.Anulata = time.Date(2026, 10, 19, 15, 0, 0, 0, time.UTC)
	date, _ = json.Marshal(c)
	fmt.Println(string(date))
}

Rezultat

{"numar":1001,"livrata":"0001-01-01T00:00:00Z","cantitate":"3"}
{"numar":1001,"reducere":10.5,"livrata":"0001-01-01T00:00:00Z","anulata":"2026-10-19T15:00:00Z","cantitate":"3"}

Exemplul 3: Map-uri, slice-uri și valori simple

Cheile unui map apar sortate. Caracterele <, > și & sunt codate ca \u003c etc., ca JSON-ul să fie sigur în HTML.

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	stoc := map[string]int{"pere": 12, "mere": 40, "caise": 0}
	a, _ := json.Marshal(stoc)
	fmt.Println(string(a))

	b, _ := json.Marshal([]any{1, "doi", 3.5, true, nil, []int{4, 5}})
	fmt.Println(string(b))

	var lipsa []string
	c, _ := json.Marshal(map[string]any{"nil": lipsa, "gol": []string{}, "html": "<b>Tom & Jerry</b>"})
	fmt.Println(string(c))

	_, err := json.Marshal(map[string]any{"f": func() {}})
	fmt.Println("Eroare:", err)
}

Rezultat

{"caise":0,"mere":40,"pere":12}
[1,"doi",3.5,true,null,[4,5]]
{"gol":[],"html":"\u003cb\u003eTom \u0026 Jerry\u003c/b\u003e","nil":null}
Eroare: json: unsupported type: func()

Greșeli frecvente

  • Scrii câmpurile cu literă mică (nume string) și obții {}. Doar câmpurile exportate ajung în JSON; folosește literă mare și eticheta pentru numele mic: Nume string `json:"nume"`.
  • Scrii eticheta greșit: `json: "nume"` (cu spațiu), `json:nume` (fără ghilimele) sau cu ghilimele obișnuite în loc de apostrofuri inverse. Eticheta este ignorată; go vet te avertizează.
  • Te aștepți ca omitempty să omită un time.Time sau o structură goală. Nu le omite; folosește omitzero.
  • Un slice nil devine null, nu []. Dacă aplicația care citește așteaptă o listă, inițializează-l cu []T{}.

Comenzi înrudite

  • encoding/json.MarshalIndent: Ca Marshal, dar scrie JSON-ul pe mai multe rânduri, indentat, ușor de citit (fișiere de configurare, afișare).
  • encoding/json.Unmarshal: Citește JSON și completează o valoare Go (structură, map, slice) dată prin pointer; potrivește cheile după etichetele json.
  • encoding/json.NewEncoder: Creează un Encoder care scrie JSON direct într-un io.Writer (răspuns HTTP, fișier, ecran); Encode scrie o valoare.
  • encoding/json.Marshaler: Interfețe pentru a controla singur forma JSON a unui tip: MarshalJSON la scriere, UnmarshalJSON la citire.