JSON Formatter Go — MarshalIndent() गाइड
मुफ़्त JSON Formatter & Beautifier को सीधे अपने ब्राउज़र में उपयोग करें — इंस्टॉलेशन की ज़रूरत नहीं।
JSON Formatter & Beautifier ऑनलाइन आज़माएं →जब मैं Go microservice पर काम करता हूँ और API response या config file inspect करनी होती है, compact JSON पहली बाधा बन जाती है — सैकड़ों nested fields वाली एक लाइन एक नज़र में लगभग कुछ नहीं बताती। Go में JSON format करने के लिए, standard library आपको सब कुछ देती है: json.MarshalIndent पहले से encoding/json में built-in है, हर Go installation के साथ आती है, और zero third-party dependencies की ज़रूरत है। यह guide पूरी तस्वीर cover करता है: struct tags, custom MarshalJSON() implementations, raw bytes को reformat करने के लिए json.Indent, json.Decoder से large files streaming, high-throughput paths के लिए go-json कब use करें, और terminal में quick formatting के लिए CLI one-liners। सभी examples Go 1.21+ use करते हैं।
- ✓json.MarshalIndent(v, "", "\t") standard library है — zero dependencies, हर Go install के साथ आती है।
- ✓Struct tags json:"field_name,omitempty" serialization keys control करते हैं और zero-value fields को output से हटाते हैं।
- ✓किसी भी type पर MarshalJSON() implement करें और उसके JSON representation को पूरी तरह control करें।
- ✓json.Indent() पहले से marshal हुए []byte को struct re-parse किए बिना reformat करता है — raw bytes के लिए तेज़।
- ✓बड़ी files (>100 MB) के लिए: सब कुछ memory में लोड किए बिना streaming के लिए json.Decoder के साथ Token() use करें।
- ✓go-json, high-throughput APIs के लिए encoding/json से 3–5× तेज़ drop-in replacement है।
JSON Formatting क्या है?
JSON formatting — जिसे pretty-printing भी कहते हैं — एक compact, minified JSON string को consistent indentation और line breaks के साथ human-readable layout में transform करता है। underlying data identical होता है; केवल whitespace बदलती है। Compact JSON network transfer के लिए optimal है जहाँ हर byte मायने रखती है; formatted JSON debugging, code review, log inspection, और config file authoring के लिए optimal है। Go का encoding/json package एक single function call से दोनों modes handle करता है — json.Marshal और json.MarshalIndent के बीच choose करके compact और indented output में toggle करें।
{"service":"payments","port":8443,"workers":4}{
"service": "payments",
"port": 8443,
"workers": 4
}json.MarshalIndent() — स्टैंडर्ड लाइब्रेरी का तरीका
json.MarshalIndent Go standard library के हिस्से encoding/json package में रहता है — कोई go get नहीं चाहिए। इसका signature है MarshalIndent(v any, prefix, indent string) ([]byte, error): prefix string हर output line के आगे जुड़ती है (लगभग हमेशा खाली छोड़ी जाती है), और indent हर nesting level पर एक बार repeat होती है। Tabs के लिए "\t" या two spaces के लिए " " pass करें।
package main
import (
"encoding/json"
"fmt"
"log"
)
type ServiceConfig struct {
Host string `json:"host"`
Port int `json:"port"`
Workers int `json:"workers"`
TLSEnabled bool `json:"tls_enabled"`
AllowedIPs []string `json:"allowed_ips"`
}
func main() {
cfg := ServiceConfig{
Host: "payments-api.internal",
Port: 8443,
Workers: 8,
TLSEnabled: true,
AllowedIPs: []string{"10.0.0.0/8", "172.16.0.0/12"},
}
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
log.Fatalf("marshal config: %v", err)
}
fmt.Println(string(data))
}
// {
// "host": "payments-api.internal",
// "port": 8443,
// "workers": 8,
// "tls_enabled": true,
// "allowed_ips": [
// "10.0.0.0/8",
// "172.16.0.0/12"
// ]
// }Tabs और spaces के बीच choice ज़्यादातर team convention है। कई Go projects tabs prefer करते हैं क्योंकि gofmt (जो Go source code format करता है) tabs use करता है। Two-space या four-space indentation तब सामान्य है जब JSON किसी JavaScript या Python consumer के लिए है। यहाँ same struct दोनों indent styles के साथ side by side:
// Tab indent — Go-native tooling में preferred
data, _ := json.MarshalIndent(cfg, "", " ")
// {
// "host": "payments-api.internal",
// "port": 8443
// }
// Two-space indent — JS/Python consumers वाली APIs के लिए सामान्य
data, _ = json.MarshalIndent(cfg, "", " ")
// {
// "host": "payments-api.internal",
// "port": 8443
// }
// Four-space indent
data, _ = json.MarshalIndent(cfg, "", " ")
// {
// "host": "payments-api.internal",
// "port": 8443
// }json.Marshal(v) use करें। यह same value argument लेता है और same error semantics रखता है, लेकिन बिना किसी whitespace के single-line JSON बनाता है।Struct Tags — Field Names और Omitempty को Control करना
Go struct tags field declarations के बाद रखे गए string literals हैं जो encoding/jsonको बताते हैं कि हर field को कैसे serialize करना है। तीन key directives हैं: json:"name" output में field का नाम बदलता है, omitempty field को तब छोड़ता है जब वह अपने type की zero value रखती हो, और json:"-" field को पूरी तरह exclude करता है — passwords, internal identifiers, या ऐसी fields के लिए उपयोगी जो service boundary से बाहर नहीं जानी चाहिए।
type UserProfile struct {
ID string `json:"id"`
Email string `json:"email"`
DisplayName string `json:"display_name,omitempty"` // empty string होने पर छोड़ें
AvatarURL *string `json:"avatar_url,omitempty"` // nil pointer होने पर छोड़ें
IsAdmin bool `json:"is_admin,omitempty"` // false होने पर छोड़ें
passwordHash string // unexported — auto excluded
}
// सभी optional fields भरे हुए user के साथ
full := UserProfile{
ID: "usr_7b3c", Email: "raj.kumar@udaharan.com",
DisplayName: "राज कुमार", IsAdmin: true,
}
// {
// "id": "usr_7b3c",
// "email": "raj.kumar@udaharan.com",
// "display_name": "राज कुमार",
// "is_admin": true
// }
// बिना optional fields वाला user — पूरी तरह छोड़ दिए जाते हैं
minimal := UserProfile{ID: "usr_2a91", Email: "priya.sharma@udaharan.com"}
// {
// "id": "usr_2a91",
// "email": "priya.sharma@udaharan.com"
// }json:"-" tag उन fields के लिए सही choice है जिन्हें उनकी value चाहे जो हो, unconditionally exclude करना है — आमतौर पर secrets, internal tracking fields, या ऐसा data जो memory में सही है लेकिन किसी भी external system में serialize नहीं होना चाहिए।
type AuthToken struct {
TokenID string `json:"token_id"`
Subject string `json:"sub"`
IssuedAt int64 `json:"iat"`
ExpiresAt int64 `json:"exp"`
SigningKey []byte `json:"-"` // कभी serialize नहीं होता
RefreshToken string `json:"-"` // कभी serialize नहीं होता
}
tok := AuthToken{
TokenID: "tok_8f2a", Subject: "usr_7b3c",
IssuedAt: 1741614120, ExpiresAt: 1741617720,
SigningKey: []byte("गुप्त"), RefreshToken: "rt_9e4f",
}
data, _ := json.MarshalIndent(tok, "", " ")
// {
// "token_id": "tok_8f2a",
// "sub": "usr_7b3c",
// "iat": 1741614120,
// "exp": 1741617720
// }
// SigningKey और RefreshToken कभी नहीं दिखतेencoding/json द्वारा किसी भी tag की परवाह किए बिना exclude होते हैं। Unexported fields में json:"-" जोड़ने की ज़रूरत नहीं — exclusion automatic है और override नहीं किया जा सकता।Custom MarshalJSON() — Non-Standard Types Handle करना
कोई भी Go type MarshalJSON() ([]byte, error) method define करके json.Marshaler interface implement कर सकता है। जब encoding/json ऐसे type से मिलता है, तो वह default reflection-based marshaling की बजाय method call करता है। यह domain types के लिए canonical Go pattern है जिन्हें specific wire representation की ज़रूरत है — monetary values, status enums, custom time formats, या कोई भी type जो data को उस तरह store करता है जो serialize होना चाहिए उससे अलग।
Custom Type — पैसे के साथ Cents-to-Decimal Conversion
package main
import (
"encoding/json"
"fmt"
"log"
)
type Money struct {
Amount int64 // floating-point drift से बचने के लिए paise में store
Currency string
}
func (m Money) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Amount float64 `json:"amount"`
Currency string `json:"currency"`
Display string `json:"display"`
}{
Amount: float64(m.Amount) / 100,
Currency: m.Currency,
Display: fmt.Sprintf("%s %.2f", m.Currency, float64(m.Amount)/100),
})
}
type Invoice struct {
ID string `json:"id"`
Subtotal Money `json:"subtotal"`
Tax Money `json:"tax"`
Total Money `json:"total"`
}
func main() {
inv := Invoice{
ID: "inv_9a2f91bc",
Subtotal: Money{Amount: 1990000, Currency: "INR"},
Tax: Money{Amount: 159200, Currency: "INR"},
Total: Money{Amount: 2149200, Currency: "INR"},
}
data, err := json.MarshalIndent(inv, "", " ")
if err != nil {
log.Fatalf("marshal invoice: %v", err)
}
fmt.Println(string(data))
}
// {
// "id": "inv_9a2f91bc",
// "subtotal": { "amount": 19900, "currency": "INR", "display": "INR 19900.00" },
// "tax": { "amount": 1592, "currency": "INR", "display": "INR 1592.00" },
// "total": { "amount": 21492, "currency": "INR", "display": "INR 21492.00" }
// }Status Enum — String Representation
type OrderStatus int
const (
StatusPending OrderStatus = iota
StatusPaid
StatusShipped
StatusCancelled
)
var orderStatusNames = map[OrderStatus]string{
StatusPending: "pending",
StatusPaid: "paid",
StatusShipped: "shipped",
StatusCancelled: "cancelled",
}
func (s OrderStatus) MarshalJSON() ([]byte, error) {
name, ok := orderStatusNames[s]
if !ok {
return nil, fmt.Errorf("अज्ञात order status: %d", s)
}
return json.Marshal(name)
}
type Order struct {
ID string `json:"id"`
Status OrderStatus `json:"status"`
}
o := Order{ID: "ord_3c7f", Status: StatusShipped}
data, _ := json.MarshalIndent(o, "", " ")
// {
// "id": "ord_3c7f",
// "status": "shipped"
// }MarshalJSON() और UnmarshalJSON() दोनों को साथ implement करें। अगर आप केवल marshaling implement करते हैं, तो JSON के माध्यम से type का round-tripping (serialize → store → deserialize) चुपचाप structure खो देगा या गलत type return करेगा। यह pair एक contract बनाता है कि type JSON round-trip से बच सकता है।UUID — String के रूप में Serialize करें
Go की standard library में कोई UUID type नहीं है। सबसे सामान्य choice github.com/google/uuid है, जो पहले से MarshalJSON() implement करता है और quoted RFC 4122 string के रूप में serialize करता है। अगर आप raw [16]byte या custom ID type use करते हैं, तो JSON output में base64-encoded binary blobs से बचने के लिए interface खुद implement करें।
import (
"encoding/json"
"fmt"
"github.com/google/uuid"
)
type AuditEvent struct {
EventID uuid.UUID `json:"event_id"` // "550e8400-e29b-41d4-a716-446655440000" के रूप में serialize होता है
SessionID uuid.UUID `json:"session_id"`
Action string `json:"action"`
ActorID string `json:"actor_id"`
OccuredAt string `json:"occurred_at"`
}
event := AuditEvent{
EventID: uuid.New(),
SessionID: uuid.MustParse("550e8400-e29b-41d4-a716-446655440000"),
Action: "user.password_changed",
ActorID: "usr_7f3a91bc",
OccuredAt: "2026-03-10T14:22:00Z",
}
data, _ := json.MarshalIndent(event, "", " ")
fmt.Println(string(data))
// {
// "event_id": "a4b2c1d0-...",
// "session_id": "550e8400-e29b-41d4-a716-446655440000",
// "action": "user.password_changed",
// "actor_id": "usr_7f3a91bc",
// "occurred_at": "2026-03-10T14:22:00Z"
// }[16]byte के रूप में store करते हैं, encoding/json उन्हें base64 string के रूप में encode करेगा — जैसे "VQ6EAOKbQdSnFkRmVUQAAA=="। हमेशा proper UUID type use करें या canonical hyphenated string format emit करने के लिए MarshalJSON() implement करें।json.MarshalIndent() पैरामीटर संदर्भ
Function signature है func MarshalIndent(v any, prefix, indent string) ([]byte, error)। दोनों prefix और indent string literals हैं — Python के indent=4 जैसा कोई numeric shorthand नहीं है।
सामान्य struct tag options:
json.Indent() — मौजूदा JSON Bytes को Reformat करना
जब आपके पास पहले से JSON का []byte हो — HTTP response body, Postgres के jsonb column, या os.ReadFile से पढ़ी गई file — तो pretty-print से पहले struct define करके unmarshal करने की ज़रूरत नहीं। json.Indent raw bytes को सीधे एक bytes.Buffer में indented output लिखकर reformat करता है।
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
)
func main() {
// upstream service से raw JSON payload simulate करना
raw := []byte(`{"trace_id":"tr_9a2f","service":"checkout","latency_ms":342,"error":null}`)
var buf bytes.Buffer
if err := json.Indent(&buf, raw, "", " "); err != nil {
log.Fatalf("indent: %v", err)
}
fmt.Println(buf.String())
}
// {
// "trace_id": "tr_9a2f",
// "service": "checkout",
// "latency_ms": 342,
// "error": null
// }Microservices में मैं जो सामान्य pattern use करता हूँ वह है structured logs में लिखने से पहले json.Indent call करना — यह negligible overhead जोड़ता है और incident के दौरान log entries को बहुत आसानी से पढ़ने योग्य बनाता है। यह function HTTP responses log करने, stored JSON strings को pretty-print करने, और format-on-read pipelines में विशेष रूप से उपयोगी है जहाँ struct definition available नहीं है।
func logResponse(logger *slog.Logger, statusCode int, body []byte) {
var pretty bytes.Buffer
if err := json.Indent(&pretty, body, "", " "); err != nil {
// Body valid JSON नहीं है — raw log करें
logger.Debug("upstream response", "status", statusCode, "body", string(body))
return
}
logger.Debug("upstream response", "status", statusCode, "body", pretty.String())
}json.Indent JSON को उससे परे fully validate नहीं करता जो whitespace insert करने के लिए structurally ज़रूरी है। Full syntax validation के लिए, पहले json.Valid(data) call करें और indent attempt से पहले false case handle करें।File और HTTP Response से JSON Format करना
Go services में दो सबसे सामान्य real-world scenarios हैं: disk पर file से JSON format करना (config files, fixture data, migration seeds) और debug logging या test assertions के लिए HTTP response bodies को pretty-print करना। दोनों same pattern follow करते हैं: bytes पढ़ें, json.Indent call करें या unmarshal करके json.MarshalIndent करें, फिर वापस लिखें या log करें।
File पढ़ें → Format करें → वापस लिखें
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"os"
)
func formatJSONFile(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("पढ़ें %s: %w", path, err)
}
if !json.Valid(data) {
return fmt.Errorf("%s में invalid JSON", path)
}
var buf bytes.Buffer
if err := json.Indent(&buf, data, "", " "); err != nil {
return fmt.Errorf("indent %s: %w", path, err)
}
if err := os.WriteFile(path, buf.Bytes(), 0644); err != nil {
return fmt.Errorf("लिखें %s: %w", path, err)
}
return nil
}
func main() {
if err := formatJSONFile("config/database.json"); err != nil {
log.Fatalf("format config: %v", err)
}
fmt.Println("config/database.json सफलतापूर्वक format हुई")
}HTTP Response → Decode → Debug Logging के लिए Pretty-Print
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
type HealthResponse struct {
Status string `json:"status"`
Version string `json:"version"`
Checks map[string]string `json:"checks"`
UptimeSec int64 `json:"uptime_seconds"`
}
func main() {
resp, err := http.Get("https://api.payments.internal/v2/health")
if err != nil {
log.Fatalf("health check: %v", err)
}
defer resp.Body.Close()
var result HealthResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
log.Fatalf("health response decode करें: %v", err)
}
pretty, err := json.MarshalIndent(result, "", " ")
if err != nil {
log.Fatalf("health response marshal करें: %v", err)
}
fmt.Printf("Health check (%d):
%s
", resp.StatusCode, string(pretty))
}
// Health check (200):
// {
// "status": "ok",
// "version": "1.4.2",
// "checks": {
// "database": "ok",
// "cache": "ok",
// "queue": "degraded"
// },
// "uptime_seconds": 172800
// }Raw Response Body → json.Indent (Struct की ज़रूरत नहीं)
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
func main() {
resp, err := http.Get("https://api.payments.internal/v2/health")
if err != nil {
log.Fatalf("request: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("body पढ़ें: %v", err)
}
var buf bytes.Buffer
if err := json.Indent(&buf, body, "", " "); err != nil {
log.Fatalf("indent: %v", err)
}
fmt.Println(buf.String())
}Go में HTTP Response से JSON Pretty Print करना
ऊपर के दो approaches सबसे सामान्य cases cover करते हैं: typed struct में decode करें फिर json.MarshalIndent call करें (तब सबसे अच्छा जब fields validate या inspect करने हों), या io.ReadAll से raw body bytes पढ़ें और सीधे json.Indent call करें (तब सबसे अच्छा जब struct definition available न हो और quick debug logging चाहिए)। Raw-bytes approach simpler है लेकिन Go type safety या field access नहीं देती — यह purely एक display transformation है। दोनों approaches large response bodies को correctly handle करती हैं जब तक पूरा body memory में fit हो।
// Pattern A: typed decode → MarshalIndent // तब use करें जब specific fields inspect या validate करने हों var result map[string]any json.NewDecoder(resp.Body).Decode(&result) pretty, _ := json.MarshalIndent(result, "", " ") fmt.Println(string(pretty)) // Pattern B: raw bytes → json.Indent // Quick debug logging के लिए use करें — struct definition नहीं चाहिए body, _ := io.ReadAll(resp.Body) var buf bytes.Buffer json.Indent(&buf, body, "", " ") fmt.Println(buf.String())
Go Projects में Command-Line JSON Formatting
कभी-कभी आपको Go program लिखे बिना सीधे terminal में JSON payload format करनी होती है। ये one-liners वे हैं जो मैं development और incident response के दौरान muscle memory में रखता हूँ।
echo '{"service":"payments","port":8443,"workers":4}' | python3 -m json.tool
# {
# "service": "payments",
# "port": 8443,
# "workers": 4
# }# केवल format करें cat api-response.json | jq . # Nested field निकालें cat api-response.json | jq '.checks.database' # Array filter करें cat audit-log.json | jq '.[] | select(.severity == "error")'
# main.go: stdin पढ़ता है, format करता है, stdout लिखता है
cat <<'EOF' > /tmp/fmt.go
package main
import ("bytes";"encoding/json";"io";"os")
func main() {
b,_:=io.ReadAll(os.Stdin)
var buf bytes.Buffer
json.Indent(&buf,b,""," ")
os.Stdout.Write(buf.Bytes())
}
EOF
echo '{"port":8080,"debug":true}' | go run /tmp/fmt.gogofmt JSON नहीं बल्कि Go source code format करता है। JSON files को gofmt से pipe न करें — यह या तो error देगा या unrecognizable output बनाएगा। JSON files के लिए jq . या python3 -m json.tool use करें।उच्च-प्रदर्शन विकल्प — go-json
अधिकांश Go services के लिए, encoding/json काफी तेज़ है। लेकिन अगर JSON marshaling आपके profiler में दिखे — high-throughput REST APIs या हर request पर large structured log lines emit करने वाली services में सामान्य — तो go-json library identical API surface के साथ 3–5× faster drop-in replacement है।
go get github.com/goccy/go-json
package main
import (
// इसे बदलें:
// "encoding/json"
// इससे — identical API, कोई और code changes नहीं:
json "github.com/goccy/go-json"
"fmt"
"log"
)
type AuditEvent struct {
RequestID string `json:"request_id"`
UserID string `json:"user_id"`
Action string `json:"action"`
ResourceID string `json:"resource_id"`
IPAddress string `json:"ip_address"`
DurationMs int `json:"duration_ms"`
}
func main() {
event := AuditEvent{
RequestID: "req_7d2e91", UserID: "usr_4421",
Action: "invoice.download", ResourceID: "inv_9a2f",
IPAddress: "203.0.113.45", DurationMs: 23,
}
data, err := json.MarshalIndent(event, "", " ")
if err != nil {
log.Fatalf("marshal: %v", err)
}
fmt.Println(string(data))
// Output encoding/json के समान — केवल speed अलग है
}github.com/bytedance/sonic available सबसे fast Go JSON library है, लेकिन यह केवल amd64 और arm64 पर चलती है (JIT compilation use करती है)। जब portable drop-in चाहिए तो go-json use करें; जब known architecture पर हों और hot path में हर microsecond चाहिए तो sonic तक पहुँचें।
Large JSON Files के साथ काम करना
json.MarshalIndent और json.Indent दोनों को पूरे payload का memory में होना ज़रूरी है। 100 MB से ऊपर की files के लिए — data exports, audit logs, Kafka consumer payloads — input stream करने और records को एक-एक करके process करने के लिए json.Decoder use करें।
json.Decoder से Large JSON Array Streaming
package main
import (
"encoding/json"
"fmt"
"log"
"os"
)
type AuditEvent struct {
RequestID string `json:"request_id"`
UserID string `json:"user_id"`
Action string `json:"action"`
Severity string `json:"severity"`
DurationMs int `json:"duration_ms"`
}
func processAuditLog(path string) error {
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("खोलें %s: %w", path, err)
}
defer file.Close()
dec := json.NewDecoder(file)
// Opening '[' token पढ़ें
if _, err := dec.Token(); err != nil {
return fmt.Errorf("opening token पढ़ें: %w", err)
}
var processed int
for dec.More() {
var event AuditEvent
if err := dec.Decode(&event); err != nil {
return fmt.Errorf("event %d decode करें: %w", processed, err)
}
// एक समय में एक event process करें — constant memory usage
if event.Severity == "error" {
fmt.Printf("[ERROR] %s: %s (%dms)
", event.UserID, event.Action, event.DurationMs)
}
processed++
}
fmt.Printf("%d audit events process हुए
", processed)
return nil
}
func main() {
if err := processAuditLog("audit-2026-03.json"); err != nil {
log.Fatalf("audit log process करें: %v", err)
}
}NDJSON — प्रति Line एक JSON Object
package main
import (
"bufio"
"encoding/json"
"fmt"
"log"
"os"
)
type LogLine struct {
Timestamp string `json:"ts"`
Level string `json:"level"`
Service string `json:"service"`
Message string `json:"msg"`
TraceID string `json:"trace_id"`
DurationMs int `json:"duration_ms,omitempty"`
}
func main() {
file, err := os.Open("service-2026-03.ndjson")
if err != nil {
log.Fatalf("log खोलें: %v", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Buffer(make([]byte, 1024*1024), 1024*1024) // प्रति line 1 MB
for scanner.Scan() {
var line LogLine
if err := json.Unmarshal(scanner.Bytes(), &line); err != nil {
continue // malformed lines skip करें
}
if line.Level == "error" {
fmt.Printf("%s [%s] %s trace=%s
",
line.Timestamp, line.Service, line.Message, line.TraceID)
}
}
if err := scanner.Err(); err != nil {
log.Fatalf("scan: %v", err)
}
}os.ReadFile से load करने पर उस पूरे buffer को heap पर allocate करेगा, GC pressure trigger करेगा, और memory-constrained containers में OOM cause कर सकता है।सामान्य गलतियाँ
समस्या: _ से error discard करने का मतलब है कि non-serializable value (channel, function, complex number) चुपचाप nil output produce करती है या downstream string(nil) call करने पर panic करती है।
समाधान: हमेशा error check करें। अगर आप ऐसे type को marshal कर रहे हैं जो हमेशा succeed करनी चाहिए, तो silent data loss से बेहतर है panicking log.Fatalf।
data, _ := json.MarshalIndent(payload, "", " ") fmt.Println(string(data)) // marshal fail होने पर empty string
data, err := json.MarshalIndent(payload, "", " ")
if err != nil {
log.Fatalf("marshal payload: %v", err)
}
fmt.Println(string(data))समस्या: fmt.Println(string(data)) JSON के बाद newline character append करता है, जो उन pipelines को corrupt करता है जो output को raw bytes के रूप में treat करते हैं — जैसे jq में pipe करना या binary protocol में लिखना।
समाधान: Binary-clean output के लिए os.Stdout.Write(data) use करें। अगर human display के लिए trailing newline चाहिए, तो उसे explicitly append करें।
data, _ := json.MarshalIndent(cfg, "", " ") fmt.Println(string(data)) // end में extra newline जोड़ता है
data, _ := json.MarshalIndent(cfg, "", " ")
os.Stdout.Write(data)
os.Stdout.Write([]byte("
")) // केवल ज़रूरत पड़ने पर explicit newlineसमस्या: omitempty के बिना, nil *string या *int pointer "field": null के रूप में serialize होता है। यह internal field names expose करता है और consumer side पर strict JSON schema validators को break कर सकता है।
समाधान: उन pointer fields में omitempty जोड़ें जो आप output में absent (null नहीं) चाहते हैं। omitempty के साथ nil *T JSON में कोई key नहीं बनाती।
type WebhookPayload struct {
EventID string `json:"event_id"`
ErrorMsg *string `json:"error_msg"` // nil होने पर null के रूप में दिखता है
}
// {"event_id":"evt_3c7f","error_msg":null}type WebhookPayload struct {
EventID string `json:"event_id"`
ErrorMsg *string `json:"error_msg,omitempty"` // nil होने पर omit
}
// {"event_id":"evt_3c7f"}समस्या: map[string]any में unmarshal करने से type information खो जाती है, manual type assertions चाहिए, और non-deterministic key order produce होती है — JSON diffs और log comparisons को कठिन बनाता है।
समाधान: Proper json tags के साथ struct define करें। Structs type-safe हैं, faster marshal होते हैं, struct definition से match करते deterministic field order produce करते हैं, और code को self-documenting बनाते हैं।
var result map[string]any json.Unmarshal(body, &result) port := result["port"].(float64) // type assertion ज़रूरी, गलत type पर panic
type ServiceStatus struct {
Service string `json:"service"`
Port int `json:"port"`
Healthy bool `json:"healthy"`
}
var result ServiceStatus
json.Unmarshal(body, &result)
port := result.Port // typed, safe, fastencoding/json बनाम विकल्प — त्वरित तुलना
किसी भी case के लिए json.MarshalIndent use करें जहाँ आप struct definition control करते हैं और formatted output चाहिए — config files, debug logging, test fixtures, और API response logging। तब json.Indent use करें जब आपके पास पहले से raw bytes हों और Go types के माध्यम से round-trip किए बिना केवल whitespace जोड़नी हो। go-json या sonic पर तभी switch करें जब profiling confirm करे कि JSON marshaling measurable bottleneck है — अधिकांश services के लिए, standard library पर्याप्त से अधिक है।
अक्सर पूछे जाने वाले प्रश्न
Go में JSON को pretty print कैसे करें?
encoding/json पैकेज से json.MarshalIndent(v, "", "\t") को call करें — दूसरा argument प्रति-लाइन prefix है (आमतौर पर खाली) और तीसरा प्रति-लेवल indent है। टैब के लिए "\t" या दो spaces के लिए " " पास करें। कोई external library नहीं चाहिए; encoding/json Go standard library के साथ आती है।
package main
import (
"encoding/json"
"fmt"
"log"
)
func main() {
config := map[string]any{
"service": "payments-api",
"port": 8443,
"region": "ap-south-1",
}
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
log.Fatalf("marshal: %v", err)
}
fmt.Println(string(data))
// {
// "port": 8443,
// "region": "ap-south-1",
// "service": "payments-api"
// }
}json.Marshal और json.MarshalIndent में क्या अंतर है?
json.Marshal compact single-line JSON बनाता है जिसमें कोई whitespace नहीं होती — network transfer के लिए आदर्श जहाँ हर byte मायने रखती है। json.MarshalIndent दो extra string parameters लेता है (prefix और indent) और इंडेंटेड, human-readable output बनाता है। दोनों functions एक ही value types accept करते हैं और ([]byte, error) return करते हैं। MarshalIndent की एकमात्र cost थोड़े अधिक output bytes और whitespace insert करने के लिए नगण्य CPU है।
import "encoding/json"
type HealthCheck struct {
Status string `json:"status"`
Version string `json:"version"`
Uptime int `json:"uptime_seconds"`
}
h := HealthCheck{Status: "ok", Version: "1.4.2", Uptime: 86400}
compact, _ := json.Marshal(h)
// {"status":"ok","version":"1.4.2","uptime_seconds":86400}
pretty, _ := json.MarshalIndent(h, "", " ")
// {
// "status": "ok",
// "version": "1.4.2",
// "uptime_seconds": 86400
// }struct unmarshal किए बिना JSON []byte को कैसे format करें?
json.Indent(&buf, src, "", "\t") का उपयोग करें। यह function मौजूदा JSON के []byte को लेता है और bytes.Buffer में इंडेंटेड version लिखता है — कोई struct definition नहीं, कोई type assertion नहीं, Go types के माध्यम से कोई round-trip नहीं। यह तब सबसे तेज़ विकल्प है जब आपके पास पहले से raw JSON bytes हों, जैसे HTTP response body या database column से।
import (
"bytes"
"encoding/json"
"fmt"
"log"
)
raw := []byte(`{"endpoint":"/api/v2/invoice","page":1,"per_page":50,"total":312}`)
var buf bytes.Buffer
if err := json.Indent(&buf, raw, "", " "); err != nil {
log.Fatalf("indent: %v", err)
}
fmt.Println(buf.String())
// {
// "endpoint": "/api/v2/invoice",
// "page": 1,
// "per_page": 50,
// "total": 312
// }json.MarshalIndent error क्यों return करता है?
encoding/json तब error return करता है जब value को JSON के रूप में represent नहीं किया जा सकता। सबसे सामान्य कारण: channel, function, या complex number को marshal करना (इनका JSON equivalent नहीं है); एक struct जो MarshalJSON() implement करता है और error return करता है; या non-string keys वाला map। महत्वपूर्ण: unexported या nil pointer field वाले struct को marshal करने से error नहीं आती — वे बस छोड़ दिए जाते हैं।
import (
"encoding/json"
"fmt"
)
// यह error return करेगा — channels JSON-serializable नहीं हैं
ch := make(chan int)
_, err := json.MarshalIndent(ch, "", " ")
fmt.Println(err)
// json: unsupported type: chan int
// यह ठीक है — omitempty के साथ nil pointer fields चुपचाप छोड़ दिए जाते हैं
type Profile struct {
ID string `json:"id"`
Avatar *string `json:"avatar,omitempty"`
}
p := Profile{ID: "usr_7b3c"}
data, _ := json.MarshalIndent(p, "", " ")
// {"id": "usr_7b3c"} — avatar छोड़ा गया, कोई error नहींGo में JSON output से field को कैसे exclude करें?
तीन तरीके हैं। पहला, json:"-" struct tag का उपयोग करें — field हमेशा उसकी value चाहे जो हो, exclude होती है। दूसरा, omitempty का उपयोग करें — field तभी exclude होती है जब वह अपने type की zero value रखती हो (nil pointer, empty string, 0, false)। तीसरा, unexported (lowercase) fields को encoding/json किसी भी tag के बिना automatically exclude करता है।
type PaymentMethod struct {
ID string `json:"id"`
Last4 string `json:"last4"`
ExpiryMonth int `json:"expiry_month"`
ExpiryYear int `json:"expiry_year"`
CVV string `json:"-"` // हमेशा exclude
BillingName string `json:"billing_name,omitempty"` // खाली होने पर exclude
internalRef string // unexported — auto exclude
}
pm := PaymentMethod{
ID: "pm_9f3a", Last4: "4242",
ExpiryMonth: 12, ExpiryYear: 2028,
CVV: "123", internalRef: "stripe:pm_9f3a",
}
data, _ := json.MarshalIndent(pm, "", " ")
// CVV, BillingName (खाली), और internalRef output में नहीं दिखतेJSON marshaling में time.Time को कैसे handle करें?
encoding/json डिफ़ॉल्ट रूप से time.Time को RFC3339Nano format में marshal करता है (जैसे "2026-03-10T14:22:00Z"), जो ISO 8601 compatible है। यदि आपको अलग format चाहिए — जैसे legacy API के लिए Unix epoch integers, या custom date-only string — time.Time embed करने वाले wrapper type पर MarshalJSON() implement करें।
import (
"encoding/json"
"fmt"
"time"
)
// Default behavior — RFC3339Nano, कोई custom code नहीं चाहिए
type AuditEvent struct {
Action string `json:"action"`
OccurredAt time.Time `json:"occurred_at"`
}
e := AuditEvent{
Action: "invoice.paid",
OccurredAt: time.Date(2026, 3, 10, 14, 22, 0, 0, time.UTC),
}
data, _ := json.MarshalIndent(e, "", " ")
// {
// "action": "invoice.paid",
// "occurred_at": "2026-03-10T14:22:00Z"
// }
// Custom: Unix timestamp integer के रूप में
type UnixTime struct{ time.Time }
func (u UnixTime) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("%d", u.Unix())), nil
}संबंधित टूल्स
James is a systems engineer and Go enthusiast who focuses on high-performance microservices, command-line tooling, and infrastructure automation. He enjoys the simplicity and explicitness of Go and writes about building fast, reliable backend systems. When not coding he explores distributed systems concepts and contributes to open-source Go libraries.
Tobias is a platform engineer who builds developer tooling and internal infrastructure in Go. He has authored several open-source CLI tools and contributes to the Go toolchain ecosystem. He writes about the cobra and urfave/cli frameworks, cross-platform binary distribution, configuration management, and the patterns that make Go an ideal language for building reliable, self-contained command-line utilities.