Golang JSON Marshal a Struct With Pointers

Simplify Complexity
1 min readApr 17, 2021
package main

import (
"encoding/json"
"fmt"
)

type Num struct {
N int
}

type Packed struct {
p
Num *Num
Name string
}

func main() {
num := &Num{N: 100}

packed := Packed{pNum: num, Name: "xx-packed-xy"}

dataInBytes, err := json.Marshal(packed)
fmt.Printf("%+v data=%s\n", err, string(dataInBytes))

unpacked := &Packed{}
err = json.Unmarshal(dataInBytes, unpacked)
fmt.Printf("%v, %+v\n", err, unpacked)
}

The above code marshals an object of type struct using a pointer. The code does not work as expected. That means the unmarshalled object does not match the input.

<nil> data={"Name":"xx-packed-xy"}
<nil> &{pNum:<nil> Name:xx-packed-xy}

The reason is the naming of the struct variable.

type Packed struct {
p
Num *Num // the lower case name is never marshalled
Name string
}

The other important feature to remember is that golang marshaller can process nested struct with pointer fields.

So you need not bother about creating a copy of the member in a struct.

package main

import (
"encoding/json"
"fmt"
)

type Num struct {
N int
}

type Packed struct {
PNum *Num
Name string
}

func main() {
num := &Num{N: 100}

packed := Packed{PNum: num, Name: "xx-packed-xy"}

dataInBytes, err := json.Marshal(packed)
fmt.Printf("%+v data=%s\n", err, string(dataInBytes))

unpacked := &Packed{}

err = json.Unmarshal(dataInBytes, unpacked)
fmt.Printf("%v %+v\n", err, unpacked.PNum)
}

Output

<nil> data={"PNum":{"N":100},"Name":"xx-packed-xy"}
<nil> &{N:100}

Summary

  1. Always name member names in upper case
  2. Use pointers as a member without hesitation.

--

--

Simplify Complexity

Golang, Distributed Systems, File Systems, Python, C/C++, Linux