How to Golang JSON Marshal and Unmarshal (With Examples!)

7 min read

JSON logo and Golang Gopher side by side for a blog post on how to golang json marshal and unmarshal

As a Go developer, you'll often need to convert between JSON data and objects. In Go, the process of converting Go data structures to JSON data is called marshaling. In this blog post, we will explore the basics of the Golang JSON marshaling feature and how to use it effectively.

Understanding Golang JSON Marshaling

JSON is a data-interchange format that is easy for both humans and machines to parse and generate. JSON data consists of a collection of key-value pairs, where each key is a string and each value can be a string, number, boolean, null, array, or object.

Go's standard library provides a package called encoding/json that contains functions and types for marshaling and unmarshaling JSON data. The json.Marshal() function is used to convert Go data structures to JSON data, and the json.Unmarshal() function is used to convert JSON data to Go data structures.

Marshaling Go Data Structures to JSON

To marshal a Go data structure to JSON, you need to define the structure and then call the json.Marshal function. The json.Marshal function takes an interface{} argument and returns a []byte slice containing the JSON data.

Let's start with a simple example where we define a struct called "Person" that represents a person's name, age, and email address.

type Person struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email"` }

In the above code, we define a struct called "Person" with three fields: "Name", "Age", and "Email". We also use struct tags to specify the JSON key names for each field.

Now, let's create an instance of the "Person" struct and marshal it to JSON.

person := Person{Name: "John Doe", Age: 30, Email: "[email protected]"} data, err := json.Marshal(person) if err != nil { log.Fatal(err) } fmt.Println(string(data))

In the above Golang json marshal code example, we create an instance of the "Person" struct and assign it to the "person" variable. We then call the json.Marshal function to marshal the "person" variable to JSON data. Finally, we convert the JSON data to a string and print it to the console.

The output of the above code will be:{"name":"John Doe","age":30,"email":"[email protected]"}.

Understanding Golang JSON Unmarshaling

To unmarshal JSON data to a Go data structure, you need to define the structure and then call the json.Unmarshal function. The json.Unmarshal function takes a []byte slice containing the JSON data and a pointer to a variable of the type you want to unmarshal the data into.

Let's continue with our "Person" struct example and create a JSON string that represents a person's data.

{ "name": "Jane Doe", "age": 25, "email": "[email protected]" }

In the above code, we define a JSON object that contains the "name", "age", and "email" keys with their respective values.

Now, let's unmarshal the JSON data to a "Person" struct.

jsonData := []byte(`{"name":"Joe","age":25,"email":"joe@example"}`) person := Person{} err := json.Unmarshal(jsonData, &person) if err != nil { log.Fatal(err) } fmt.Println(person.Name, person.Age, person.Email)

In the above code, we define a []byte slice containing the JSON data and assign it to the "jsonData" variable. We then instantiate a "Person" variable called "person" and call the json.Unmarshal function to unmarshal the "jsonData" variable to the "person" variable. Finally, we print the person's name, age, and email to the console.

The output of the above code will be: Joe 25 joe@example

Should the json data be a list of Person, you would need to modify your person variable to instantiate a []Person{} struct and pass that through to the Unmarshal function. From there, you would be able to iterate the list using a for loop, or convert it in to a golang map for quick and efficient lookups.

Want to be the first to hear about Go jobs?

Sign up to the Work in Golang weekly digest:

Using JSON Tags to Define Key Names

In our previous examples, we used struct tags to define the key names in the JSON data. You can also use tags to specify whether a field should be included in the JSON data, and whether it should be treated as an empty value.

Let's modify our "Person" struct example to include these additional tags.

type Person struct { Name string `json:"name,omitempty"` Age int `json:"age,omitempty"` Email string `json:"email,omitempty"` Password string `json:"-"` }

In the above code, we use the omitempty option to specify that a field should be omitted from the JSON data if its value is zero or an empty string. We also use a - tag to specify that the "Password" field should be ignored during marshaling and unmarshaling.

Let's create a "Person" struct instance with some fields empty and password and marshal it to JSON.

person := Person{Name: "John Doe", Password: "secret"} data, err := json.Marshal(person) if err != nil { log.Fatal(err) } fmt.Println(string(data))

In the above code, we create a "Person" struct instance with only the "Name" and "Password" fields filled in. We then call the json.Marshal function to marshal the "person" variable to JSON data.

The output of the above code will be: {"name":"John Doe"}

As you can see, the "Age" and "Email" fields were omitted because they were empty, and the "Password" field was ignored.

Decode incoming JSON requests

In a more practical example, we might like to accept an incoming request to our server and then decode it into an object. For this the json package offers us the NewDecoder() and Decode() chained methods which accepts the value of the in incoming *http.Request body and then decodes it into the Person struct.

type Person struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email"` } func main() { http.HandleFunc("/api/human", func(w http.ResponseWriter, r *http.Request) { var person Person err := json.NewDecoder(r.Body).Decode(&person) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } fmt.Println(person) }) log.Fatal(http.ListenAndServe(":8080", nil)) }

In the above code, we define an HTTP handler function for the /api/human endpoint. Inside the handler function, we create a new Person struct instance and use the json.NewDecoder function to create a new JSON decoder that reads from the request body. We then call the Decode method on the decoder to unmarshal the JSON data into the person variable. From here, print the value to console, but you could save this data to a database, or make use of it in your application.

Wrapping up...

Golang JSON marshaling and unmarshaling is an essential part of working with web services and APIs. Go's "encoding/json" package provides a simple and effective way to convert Go data structures to JSON data and vice versa. With the ability to define JSON key names and control the inclusion of fields in the JSON data, Go makes it easy to work with JSON data in your applications.

In this blog post, we covered the basics of Golang JSON marshaling and unmarshaling features and provided multiple examples to demonstrate their use. By following the examples in this post, you should be able to effectively marshal and unmarshal JSON data in your own Go applications.