Processing JSON object


JSON is a commonly used and powerful data-interchange format, and Go provides a built-in json package to handle it. Let’ see the following example:

  1. package main
  2. import (
  3. "encoding/json"
  4. "log"
  5. "fmt"
  6. )
  7. type People struct {
  8. Name string
  9. age int
  10. Career string `json:"career"`
  11. Married bool `json:",omitempty"`
  12. }
  13. func main() {
  14. p := &People{
  15. Name: "Nan",
  16. age: 34,
  17. Career: "Engineer",
  18. }
  19. data, err := json.Marshal(p)
  20. if err != nil {
  21. log.Fatalf("JSON marshaling failed: %s", err)
  22. }
  23. fmt.Printf("%s\n", data)
  24. }

And the execution result is shown as follows:

  1. {"Name":"Nan","career":"Engineer"}

The Marshal function is used to serialize an interface into a JSON object. In our example, it encodes a People struct:

(1) The Name member is encoded as our expectation:

  1. "Name":"Nan"

(2) Where is the age field? We can’t find it in our result. The cause is only exported members of struct can be marshaled, so that means only the name whose first letter capitalized can be encoded into JSON object (In our example, you should use Age instead of age).

(3) The name of Career field is career, not Career:

  1. "career":"Engineer"

That’s because the following tag: json:"career", which tells the Marshal function to use career in the JSON object.

(4) We also can’t see Married in the result although it has been exported, the magic behind is the json:",omitempty" tag which tells Marshal function no need to encode this member if it uses the default value.

There is another Unmarshal function which is used to parse a JSON object. See the following example which extends from the above one:

  1. package main
  2. import (
  3. "encoding/json"
  4. "log"
  5. "fmt"
  6. )
  7. type People struct {
  8. Name string
  9. age int
  10. Career string `json:"career"`
  11. Married bool `json:",omitempty"`
  12. }
  13. func main() {
  14. var p People
  15. data, err := json.Marshal(&People{Name: "Nan", age: 34, Career: "Engineer", Married: true})
  16. if err != nil {
  17. log.Fatalf("JSON marshaling failed: %s", err)
  18. }
  19. err = json.Unmarshal(data, &p)
  20. if err != nil {
  21. log.Fatalf("JSON unmarshaling failed: %s", err)
  22. }
  23. fmt.Println(p)
  24. }

The running result is like this:

  1. {Nan 0 Engineer true}

We can see the JSON object is decoded successfully.

Besides Marshal and Unmarshal functions, the json package also provides Encoder and Decoder structs which are used to process JSON object from stream. E.g., It is not uncommon to see code which handle HTTP likes this:

  1. func postFunc(w http.ResponseWriter, r *http.Request) {
  2. ......
  3. if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
  4. http.Error(w, err.Error(), http.StatusBadRequest)
  5. return
  6. }
  7. ......
  8. }

Because the mechanism of both methods are similar, it is not necessary to overtalk Encoder and Decoder here.

References:
Package json;
The Go Programming Language.