-1

I have simple program in GO to parse JSON:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonData := `{"aaa": {"bbb": {"ccc": [{"file_1": "file.jpg", "file_2": "file.png"}]}}}`

    var result map[string]map[string]map[string]interface{}
    json.Unmarshal([]byte(jsonData), &result)

    files := result["aaa"]["bbb"]["ccc"].(map[string]interface{})

    for key, value := range files {
        fmt.Println(key, value)
    }
}

https://go.dev/play/p/dxv8k4pI7uX

I would like to receive list of files, so response should be:

file_1 file.jpg file_2 file.png

but this code return me error:

panic: interface conversion: interface {} is []interface {}, not map[string]interface {}

What I'm doing wrong?

sogafo
  • 21
  • 1
  • 2
  • The value of `ccc` is a JSON array, so after unmarshaling it will be of type `[]any`, a slice, not a map. Type assert `[]any`, use a loop over it, and type assert `map[string]any` of the elements, and use another loop to print elements of this map: https://go.dev/play/p/q0WRiWqiRE_O – icza Oct 17 '22 at 17:59

1 Answers1

1

The type of result["aaa"]["bbb"]["ccc"] is []interface{} since the json has an array of maps.

One solution is to change the declaration of result to match the json schema:

var result map[string]map[string]map[string][]map[string]string

Alternatively, you can keep your definition of interface{} but then you have additional steps to do the type asserts at each level:

var result map[string]map[string]map[string]interface{}
json.Unmarshal([]byte(jsonData), &result)

fileList := result["aaa"]["bbb"]["ccc"].([]interface{})

for _, fileI := range fileList {
    for key, value := range fileI.(map[string]interface{}) {
        fmt.Println(key, value.(string))
    }
}

Edit: This 2nd approach is the same as @icza's in the comment above.

craigb
  • 1,081
  • 1
  • 9