Use Go for JSON processing

The basics of marshaling and unsealing JSON

JSON stands forJavaScriptObject notation, which is a very convenient way to exchange structured data. And it is very popular, especially when interacting with APIs.

Go provides top-level support for JSON in its standard library,Thisencoding/jsonpackage.

Compared with loosely typed languages, decoding JSON is more complicated. In JavaScript, all you need to do isJSON.parse(). Python hasjson.loads(), And PHP hasjson_decode(). They are just dumping values without problems, but to be strongly typed, you need to do more work to match the types.

JSON has 3 basic types:Boolean value,digital,Strings,In conjunction withArraywithObjectBuild complex structures.

Go's terminology callmarshalThe process of generating JSON strings from data structures, andUngroupThe act of parsing JSON into a data structure.

JSON string

input := `{"firstname": "Bill", "surname": "Gates"}`

Unmarshal JSON

This is an example taken from JSONMozilla's MDN

{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
      "powers": [
        "Radiation resistance",
        "Turning tiny",
        "Radiation blast"
      ]
    },
    {
      "name": "Madame Uppercut",
      "age": 39,
      "secretIdentity": "Jane Wilson",
      "powers": [
        "Million tonne punch",
        "Damage resistance",
        "Superhuman reflexes"
      ]
    },
    {
      "name": "Eternal Flame",
      "age": 1000000,
      "secretIdentity": "Unknown",
      "powers": [
        "Immortality",
        "Heat Immunity",
        "Inferno",
        "Teleportation",
        "Interdimensional travel"
      ]
    }
  ]
}

How do we parse it into a Go data structure? Of course, we need a matching data structure. We have 5 basic types and a series of objects. Let's start with the basic types:

type squad struct {
    SquadName string
    HomeTown string
    Formed int
    SecretBase string
    Active bool
}

We need to define JSON as[]byte, like this:

input := []byte(`
    {
        "squadName": "Super hero squad",
        [...]
    }
`)

We can unmarshal JSON into a squad instance:

s := squad{}
err := json.Unmarshal(input, &s)
if err != nil {
    panic(err)
}
fmt.Printf("%v", s)

This will print

{Super hero squad Metro City 2016 Super tower true}

play

Please note that for complaints about missing matches between JSON values and structures, we have no errors and they will be ignored.

Let's make sure that json.Unmarshal() will get all our fields, including:

type squad struct {
	SquadName  string
	HomeTown   string
	Formed     int
	SecretBase string
	Active     bool
	Members    []Member
}

type Member struct { Name string Age int SecretIdentity string Powers []string }

play

Remember to have common (uppercase) attributes in your structure.

Rename JSON field name

In this case, everything is fine, because JSON has compatible file names. What if you want to map JSON to other fields in the structure?

For example, if the member name is passed asmember_name, But you want to store it inNameinstead?

Use the following syntax:

type Member struct {
	Name string `json:"member_name"`
}

Ignore JSON fields

Use the following syntax:

type Member struct {
	Name string `json:"-"`
}

When marshaling/unmarshaling, the "Name" field will be ignored.

Convert JSON field type

You can use markup to annotate the type that JSON is converted to:

type Member struct {
    Age       int `json:"age,string"`
}

The member structure has aAgeExpressed asint. If you want it to be astringInstead, but JSON passedint?

Use type annotation:

type Member struct {
    Age       json.Number `json:"age,Number"`
}

The Number type is an alias forstring.

Learn more about tags inGo to label description

Marshal JSON

Now, we may want to construct a JSON string from our data structure. For example, this might be a program that uses a country code and returns the corresponding country/region details in JSON format.

package main

import ( “encoding/json” “fmt” )

type country struct { Name string }

func main() { country_code := “US”

<span style="color:#a6e22e">the_country</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">country</span>{}

<span style="color:#66d9ef">switch</span> <span style="color:#a6e22e">country_code</span> {
<span style="color:#66d9ef">case</span> <span style="color:#e6db74">"US"</span>:
	<span style="color:#a6e22e">the_country</span>.<span style="color:#a6e22e">Name</span> = <span style="color:#e6db74">"United States"</span>
}

<span style="color:#a6e22e">c</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Marshal</span>(<span style="color:#a6e22e">the_country</span>)
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
	panic(<span style="color:#a6e22e">err</span>)
}

<span style="color:#75715e">// c is now a []byte containing the encoded JSON

fmt.Print(string(c)) }

play

After execution, the program will print{"Name":"United States"}.

json.Marshal()Return a[]byte, So it must be converted to a string when passed tofmt.Print(), Otherwise you will see a seemingly meaningless list of numbers (but they are meaningful because they are the actual bytes that make up the string).

json.Marshal()Basic types and composite types, such as tiles and maps, will be handled correctly.

read more

read moreOn the Go blogAnd inThisencoding/jsonPackage file


More tutorials: