There was a recent experience when I was playing around with Go-lang’s struct and JSON marshal. Take a look at below example

package main

import (
   "fmt"
   "encoding/json"
)

type Trip struct {
   tripId string
   tripType string
}

func main() {
    trip := Trip{tripType: "air"}
    fmt.Println(trip)

    tripJson, err := json.Marshal(trip)
    fmt.Println(err)
    fmt.Println(string(tripJson))
}

Below is output

{ air}
<nil>
{}

Did you notice the above code? Within the same package printing trip returns the data ({ air}) correctly but tripJson returns empty ({}) with no error. It’s because the json package will silently ignore private fields in your struct.

Un-exported / private fields.

Any method or variables starting with a small case letter will be considered as private / Unexported fields. That’s not how “privacy” works in Go

In the above case, json is a separate package, so the json package will not have access for setting/getting private / Unexported fields.

Fixing above struct

package main

import (
   "fmt"
   "encoding/json"
)

type Trip struct {
   TripId string
   TripType string
}

func main() {
    trip := Trip{TripType: "air"}

    tripJson, _ := json.Marshal(trip)
    fmt.Println(string(tripJson))
}

Below is output

{"TripId":"","TripType":"air"}

JSON module calling private fields with Struct tags

package main

import (
   "fmt"
   "encoding/json"
)

type Trip struct {
   tripId string `json:"trip_id"`
   tripType string `json:"trip_type"`
}

func main() {
    trip := Trip{tripType: "air"}
    fmt.Println(trip)

    tripJson, err := json.Marshal(trip)
    fmt.Println(err)
    fmt.Println(string(tripJson))
}

With the above code, go vet will throw warnings for using exported fields when it is tagged with a json tag.

➜go vet trip/trip.go
trip/trip.go:9:4: struct field tripId has json tag but is not exported
trip/trip.go:10:4: struct field tripType has json tag but is not exported

It’s always safe to use json tags even when keys are the same, this helps to avoid mistakes to some extent. When invoking vet would show warnings when you are using private variables with json tag.

Note: Go compiler still will not throw error for above scenario.

➜go run trip/trip.go
{ air}
<nil>
{}