I’ve been writing some dynamic languages before, and I think parsing JSON is very easy. It usually takes only a few lines of code to get a parsed JSON object. The Go json package allows you to easily read and write JSON data in your application. Generating a JSON scenario is relatively simple. Json.marshal () generates THE JSON data based on the structure that is passed in. Parsing JSON parses the data into structures, and because of the free-grouping nature of the JSON format, especially complex JSON data, it can be confusing for novices to declare the types of structures to accept JSON data. In my recent work, I had to parse JSON data persisted by JS and PHP programs, so it took me about two afternoons to figure out how to declare structure types for common JSON data. The following are the details.

Parsing simple JSON

package main

import (
	"fmt"
	"encoding/json"
	"time"
	
)

func main() {
    type FruitBasket struct {
        Name    string 
        Fruit   []string
        Id      int64 `json:"ref"} jsonData := []byte(' {"Name": "Standard"."Fruit": [
             "Apple"."Banana"."Orange"]."ref": 999,
        "Created": "2018-04-09T23:00:00Z"
    }`)

    var basket FruitBasket
    err := json.Unmarshal(jsonData, &basket)
    iferr ! = nil { fmt.Println(err) } fmt.Println(basket.Name, basket.Fruit, basket.Id) fmt.Println(basket.Created) }Copy the code

Note: due to json. The UnMarshal () method receives the byte slices, so first need to convert a json string to byte section c: = [] byte (s) Playground url: play.golang.org/p/mcB6Kb6zC…

Parse JSON for an embedded object

“Fruit” : {“Name”, “Apple”, “PriceTag”: “$1”}

    jsonData := []byte(`
    {
        "Name": "Standard"."Fruit" : {"Name": "Apple"."PriceTag": "The $1"},
        "ref": 999,
        "Created": "2018-04-09T23:00:00Z"} `)Copy the code

So the structure type should be declared like this

type Fruit struct {
    Name string `json":Name"`
    PriceTag string `json:"PriceTag"`}type FruitBasket struct {
    Name    string 
    Fruit   Fruit
    Id      int64 `json:"ref"'// declare a json key Created time.time}Copy the code

Playground url: play.golang.org/p/dqw6tLb4J…

Parse JSON(Embed Array of Object)

If the Fruit value in the JSON object above is now

"Fruit": [{"Name": "Apple"."PriceTag": "The $1"
	},
	{
	    "Name": "Pear"."PriceTag": "The $15 ".}]Copy the code

In this case, simply change the parse JSON structure to []Fruit

type Fruit struct {
	Name string `json:"Name"`
	PriceTag string `json:"PriceTag"`}type FruitBasket struct {
    Name    string 
    Fruit   []Fruit
    Id      int64 `json:"ref"'// declare a json key Created time.time}Copy the code

Parse a JSON object with a dynamic Key

Let’s do a complex workaround. If we change the above array of objects to an object of object whose Key is the ID of the fruit, for example

"Fruit" : {
	"1": {
		"Name": "Apple"."PriceTag": "The $1"
	},
	"2": {
		"Name": "Pear"."PriceTag": "The $15 ".}}Copy the code

So how do we declare a Fruit field as a map with a Key of type string and a value of type Fruit

type Fruit struct {
    Name string `json:"Name"`
    PriceTag string `json:"PriceTag"`}type FruitBasket struct {
    Name    string 
    Fruit   map[string]Fruit
    Id      int64 `json:"ref"'// declare a json key Created time.time}Copy the code

The sample code

package main

import (
	"fmt"
	"encoding/json"
	"time"
	
)

func main() {
    type Fruit struct {
        Name string `json:"Name"`
        PriceTag string `json:"PriceTag"`}type FruitBasket struct {
        Name    string 
        Fruit   map[string]Fruit
        Id      int64 `json:"ref"} jsonData := []byte(' {"Name": "Standard"."Fruit" : {
	    "1": {
		"Name": "Apple"."PriceTag": "The $1"
	    },
	    "2": {
		"Name": "Pear"."PriceTag": "The $15 ".}},"ref": 999,
        "Created": "2018-04-09T23:00:00Z"
    }`)

    var basket FruitBasket
    err := json.Unmarshal(jsonData, &basket)
    iferr ! = nil { fmt.Println(err) }for _, item := range basket.Fruit {
	fmt.Println(item.Name, item.PriceTag)
    }
}
Copy the code

Playground url: play.golang.org/p/fh8JKa6pK…

Parsing JSON data containing arbitrary arrays and objects

The encode/ JSON package also provides an alternative way to parse JSON data, as it is difficult to declare structure types for JSON data containing any hierarchy. The encoding/json package uses:

  • Map [string]interface{} Stores JSON objects
  • []interface Stores a JSON array

Js.unmarshl will store any valid JSON data into a value of type Interface {}. By using the null interface type we can store any value, but using this type as a value requires a type assertion first.

Example code:

jsonData := []byte(`{"Name":"Eve"."Age": 6,"Parents": ["Alice"."Bob"]}`)

var v interface{}
json.Unmarshal(jsonData, &v)
data := v.(map[string]interface{})

for k, v := range data {
    switch v := v.(type) {
    case string:
        fmt.Println(k, v, "(string)")
    case float64:
        fmt.Println(k, v, "(float64)")
    case []interface{}:
        fmt.Println(k, "(array):")
        for i, u := range v {
            fmt.Println("", i, u)
        }
    default:
        fmt.Println(k, v, "(unknown)")}}Copy the code

Although storing JSON data in an empty interface type can be used to parse JSON data of any structure, there are still some uncontrollable areas in practical application, such as converting numeric string values to float values, so the type assertion error is often reported when running. Therefore, in the case of the JSON structure is determined, it is preferred to use the structure type declaration, JSON data into the structure of the way to parse JSON.