Skip to content

How to Fix Go JSON Marshal Omitting Unexported Fields

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about How to Fix Go JSON Marshal Omitting Unexported Fields. We cover key concepts, practical examples, and best practices.

Go json.Marshal silently omits unexported (lowercase) struct fields. This causes data loss without any error, making it hard to debug why fields are missing from JSON output.

Quick Fix

Wrong

type User struct {
    name  string
    email string
}

u := User{name: "Alice", email: "alice@example.com"}
bytes, _ := json.Marshal(u)
fmt.Println(string(bytes))
{}

Both fields are unexported, so json.Marshal produces an empty JSON object.

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

u := User{Name: "Alice", Email: "alice@example.com"}
bytes, _ := json.Marshal(u)
fmt.Println(string(bytes))
{"name":"Alice","email":"alice@example.com"}

Fix with custom MarshalJSON

type User struct {
    name  string
    email string
}

func (u User) MarshalJSON() ([]byte, error) {
    return json.Marshal(map[string]string{
        "name":  u.name,
        "email": u.email,
    })
}

Fix for nested structs

type Address struct {
    Street string `json:"street"`
    City   string `json:"city"`
}

type User struct {
    Name    string  `json:"name"`
    Address Address `json:"address"`
}

Prevention

  • Always export struct fields that should appear in JSON output.
  • Add explicit JSON tags with json:"fieldname" for all exported fields.
  • Test JSON marshaling in unit tests with specific output assertions.
  • Use json.MarshalIndent for debugging to see exactly which fields are serialized.
  • Run go vet to detect structs that might have unintended JSON behavior.

DodaTech Tools

Doda Browser's Go JSON validator shows how a struct will be serialized before deployment. DodaZIP archives serialization configurations. Durga Antivirus Pro detects sensitive data exposure through JSON marshaling of unexported fields.

Common Mistakes with json marshal unexported

  1. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  2. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  3. Using head and tail instead of pattern matching, causing runtime errors on empty lists

These mistakes appear frequently in real-world GO code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

Why does Go not include unexported fields in JSON output?

Go's encoding/json package uses reflection to access struct fields. Reflection can only access exported fields. This is a language design choice to enforce encapsulation. Unexported fields are intentionally excluded.

Can I marshal unexported fields using a different approach?

Yes, implement the json.Marshaler interface with a custom MarshalJSON() method that manually constructs the JSON output from the unexported fields.

Does `json.Unmarshal` also skip unexported fields?

Yes, json.Unmarshal cannot set unexported fields. JSON keys that match unexported fields are silently ignored. Use exported fields or implement json.Unmarshaler for custom unmarshaling.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro