Welcome to Just Enough Go ! This is the first in a series of articles about the Go programming language in which I will be covering some of the most commonly used Go standard library packages e.g. encoding/json, io, net/http, sync etc. I plan to keep these relatively short and example driven.
the code is available in this GitHub repo
I would be more than happy to take suggestions on specific Go topics which you would like to me cover! Feel free to tweet or just drop a comment 😃
This article covers the encoding/json package which handles conversion between JSON and Go types (as per RFC 7159). Let's jump right in!
Converting a Go type into JSON
Marshal
A common option is to use the Marshal function whose signature is:
func Marshal(v interface{}) ([]byte, error)
Here is an example:
func main() {
profile := Profile{Email: "abhirockzz@gmail.com", Username: "abhirockzz", Blogs: []Blog{
Blog{BlogName: "devto", URL: "https://dev.to/abhirockzz/"},
Blog{BlogName: "medium", URL: "https://medium.com/@abhishek1987/"},
}}
jsonData, err := json.Marshal(&myprofile)
//jsonData, err := json.MarshalIndent(&profile, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(jsonData))
}
you can use
MarshalIndent(commented) to indent the JSON output
Encoder
While Marshal deals in byte arrays ([]byte), an Encoder is generic and lets you work with an io.Writer which you can define to be the sink for JSON data i.e. you can specify any type which implements the io.Writer interface e.g. this could be standard out (os.Stdout), or an HTTP response (http.ResponseWriter), etc.
func main() {
profile := Profile{Email: "abhirockzz@gmail.com", Username: "abhirockzz", Blogs: []Blog{
Blog{BlogName: "devto", URL: "https://dev.to/abhirockzz/"},
Blog{BlogName: "medium", URL: "https://medium.com/@abhishek1987/"},
}}
encoder := json.NewEncoder(os.Stdout)
err := encoder.Encode(&profile)
if err != nil {
panic(err)
}
}
Use NewEncoder to specify the io.Writer. When you call Encode, the conversion takes place and the JSON is writer to io.Writer you specified.
Here is an example of how it would work with an HTTP response:
func main() {
profile := Profile{Email: "abhirockzz@gmail.com", Username: "abhirockzz", Blogs: []Blog{
Blog{BlogName: "devto", URL: "https://dev.to/abhirockzz/"},
Blog{BlogName: "medium", URL: "https://medium.com/@abhishek1987/"},
}}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
encoder := json.NewEncoder(w)
err := encoder.Encode(&profile)
if err != nil {
panic(err)
}
})
http.ListenAndServe(":8080", nil)
}
Converting JSON data to a Go type
Unmarshal
Given JSON in form of a byte array, Unmarshal stores the JSON parsing result to a pointer of the Go data type you specify (typically a struct)
func Unmarshal(data []byte, v interface{}) error
Here is a simple example:
func main() {
jsonData := `{"email":"abhirockzz@gmail.com","username":"abhirockzz","blogs":[{"name":"devto","url":"https://dev.to/abhirockzz/"},{"name":"medium","url":"https://medium.com/@abhishek1987/"}]}`
var profile Profile
err := json.Unmarshal([]byte(jsonData), &profile)
if err != nil {
panic(err)
}
...
}
Decoder
Decoder provides a generic way of unmarshalling JSON data by allowing you to specify the source of JSON input in the form of an io.Reader as opposed to a byte array.
func main() {
jsonData := `{"email":"abhirockzz@gmail.com","username":"abhirockzz","blogs":[{"name":"devto","url":"https://dev.to/abhirockzz/"},{"name":"medium","url":"https://medium.com/@abhishek1987/"}]}`
jsonDataReader := strings.NewReader(jsonData)
decoder := json.NewDecoder(jsonDataReader)
var profile Profile
err := decoder.Decode(&profile)
if err != nil {
panic(err)
}
...
}
We start by creating an io.Reader from the JSON string data using a shortcut strings.NewReader. We can then instantiate the decoder using NewDecoder and simply use decode with a pointer to the Profile struct to which the result is stored
That's all for this blog! Stay tuned for more and don't forget to like and follow 😃😃

Top comments (1)
I think this article is omitting a critical part: The definition of
Profile. A reader that doesn't know how to defineProfilewill not be able to reproduce this. Looking at your github code will probably help, but the key to json handling in Go withstructsis in the annotations on thestruct-- which is not mentioned here.Note:
Profilecould also be amap[string]interface{}(which I'd not recommend to use!!).