-2

I have json object that consists sub object of array. how can I print particular sub object in json. here is my code

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    //Simple Employee JSON which we will parse
    empArray := `{"meta":[
        {
            "id": 1,
            "name": "Mr. Boss",
            "department": "",
            "designation": "Director"
        },
        {
            "id": 11,
            "name": "Irshad",
            "department": "IT",
            "designation": "Product Manager"
        },
        {
            "id": 12,
            "name": "Pankaj",
            "department": "IT",
            "designation": "Team Lead"
        }
    ]}`

    // Declared an empty interface of type Array
    var results []map[string]interface{}

    // Unmarshal or Decode the JSON to the interface.
    json.Unmarshal([]byte(empArray['meta']), &results)

    fmt.Println(results)
}

I'm getting below error while doing soo..

./test.go:35:23: cannot convert empArray['\u0000'] (type byte) to type []byte
./test.go:35:33: invalid character literal (more than one character)

with in the empArray array object, I wanted to print meta object that consists array of employees. Please help me to accomplish this.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
ajay
  • 328
  • 1
  • 5
  • 17

2 Answers2

2

You are almost there. Parse the entire document and then pick out the part you want.

    var results map[string][]interface{}
    json.Unmarshal([]byte(empArray), &results)
    fmt.Println(results["meta"])
Adirio
  • 5,040
  • 1
  • 14
  • 26
  • Thanks Bryce Donovan for your quick answer. – ajay Feb 28 '20 at 07:08
  • Please let me know how we can do the same if we have object of objects in `meta` object just like below.```{"meta":{"data":[ { "id": 1, "name": "Mr. Boss", "department": "", "designation": "Director" }, { "id": 11, "name": "Irshad", "department": "IT", "designation": "Product Manager" }, { "id": 12, "name": "Pankaj", "department": "IT", "designation": "Team Lead" } ]}}``` – ajay Feb 28 '20 at 07:09
  • @ajay In my answer I provided the Go way of unmarshalling JSON objects including the new syntax you mention here. – Adirio Feb 28 '20 at 07:50
  • yeah you are right. but my question is like, how can we get nested object data. here, I wanted to get `data` object that is nested by `meta`. Im trying this `var results map[string][]interface{} json.Unmarshal([]byte(empArray), &results) fmt.Println(results["meta"]['data'])`. but Im getting error 'more than one character literal'. is it correct? – ajay Feb 28 '20 at 08:03
  • Single quotes (`'`) and double quotes (`"`) are not interchangeable in Go. https://play.golang.org/p/JsQUZhZWExj shows how using `'` yields the same error. The problem is not related with parsing JSON, but with Go basics. Please follow the Go Tour: https://tour.golang.org/welcome/1 – Adirio Mar 02 '20 at 08:11
2

You should use custom structs:

type Employee struct {
    ID          int    `json:"id"`
    Name        string `json:"name"`
    Department  string `json:"department"`
    Designation string `json:"designation"`
}

type Employees struct {
    Meta []Employee `json:"meta"`
}

When you try to unmarshal the provided string into a Employees var it will read the annotations and know where to place each field. You can find the working example at Golang Playground. I added a string representation to the Employee struct so that fmt.Println output is more redable.

In the case of having an extra nested key ({meta: {data: [...]}}), the types would be as follows:

type Employee struct {
    ID          int    `json:"id"`
    Name        string `json:"name"`
    Department  string `json:"department"`
    Designation string `json:"designation"`
}

type EmployeesData struct {
    Data []Employee `json:"data"`
}

type Employees struct {
    Meta EmployeesData `json:"meta"`
}

You can find the working example at Golang Playground too.

NOTE: I do not have context to name the structs properly, so I used Employees and EmployeesData but you should use more descriptive names that help understanding what the whole object represents and not only the meta and data fields.

Adirio
  • 5,040
  • 1
  • 14
  • 26
  • Hello Adirio, thanks for your answer. but I just don't wanna create separate struct template for every object. @Bryce Donovan's answer seems somewhat relatable to me without creating struct template. I asked him a question in the comments about nested object and please answer it if possible without creating struct templates – ajay Feb 28 '20 at 10:08
  • Hi Ajay, creating structs is how it should be done in Go. Using maps and slices of `interface{}` would require a lot of checks that are already handled by the structs themselves as they know the type. By using maps and slices of `interface{}`, it seems like you are trying to program in Go like if it was Python or JS. – Adirio Mar 02 '20 at 08:31