How can we read a json file as json object in golang

Aishwarya picture Aishwarya · Dec 14, 2016 · Viewed 30.4k times · Source

I have a JSON file stored on the local machine. I need to read it in a variable and loop through it to fetch the JSON object values. If I use the Marshal command after reading the file using the ioutil.Readfile method, it gives some numbers as an output. These are my few failed attempts,

Attempt 1:

plan, _ := ioutil.ReadFile(filename) // filename is the JSON file to read
var data interface{}
err := json.Unmarshal(plan, data)
if err != nil {
        log.Error("Cannot unmarshal the json ", err)
      }
fmt.Println(data)

It gave me following error,

time="2016-12-13T22:13:05-08:00" level=error msg="Cannot unmarshal the json json: Unmarshal(nil)"
<nil>

Attempt 2: I tried to store the JSON values in a struct and then using MarshalIndent

generatePlan, _ := json.MarshalIndent(plan, "", " ") // plan is a pointer to a struct
fmt.Println(string(generatePlan))

It give me the output as string. But if I cast the output to string then I won't be able to loop it as JSON object.

How can we read a JSON file as JSON object in golang? Is it possible to do that? Any help is appreciated. Thanks in advance!

Answer

John S Perayil picture John S Perayil · Dec 14, 2016

The value to be populated by json.Unmarshal needs to be a pointer.

From GoDoc :

Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.

So you need to do the following :

plan, _ := ioutil.ReadFile(filename)
var data interface{}
err := json.Unmarshal(plan, &data)

Your error (Unmarshal(nil)) indicates that there was some problem in reading the file , please check the error returned by ioutil.ReadFile


Also please note that when using an empty interface in unmarshal, you would need to use type assertion to get the underlying values as go primitive types.

To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null

It is always a much better approach to use a concrete structure to populate your json using Unmarshal.