Search code examples
jsonstringdictionarygomarshalling

How to retrieve nested map data "json.unmarshal()" as empty interface


This seems to be an easy question, but I haven't figured out how to do it: I have a nested map item, which when printed out is like the following:

fmt.Println("s3Info:", s3Info)

printout:

s3Info: [[map[s3Config:map[bucket:testbucket-data s3Key:runs/6033fd684304200011ef3bc5/init/03a78d21-446a-41bc-b4c1-eb66e04f45e2/52c8a076-f6c4-4180-8625-38ca52482628] size:158971 type:s3 varType:File]]

I wonder how can I get the value of bucket and s3Key from the object s3Info?

I tried to use s3Info.s3Config to access s3Config, but then got the following error:

go/api_default_service_data_item.go:659:46: s3Info.s3Config undefined (type interface {} is interface with no methods)

I also tried to use s3Info["s3Config"] to access s3Config, but then got the following error:

go/api_default_service_data_item.go:660:46: invalid operation: s3Info["s3Config"] (type interface {} does not support indexing)

ADDED: The code is part of a program which processes the query response from an API endpoint, the following is the code:

var runData map[string]interface{}

json.Unmarshal(body, &runData)

p := runData["p"].(map[string]interface{})
init := p["init"].(map[string]interface{})
outputs := init["outputs"].(map[string]interface{})
for key, s3Info := range outputs {
    // printout s3Info
    fmt.Println("s3Info:", s3Info)
    // check type
    switch c := s3Info.(type) {
        case string:
            fmt.Println("Key:", key, "=>", "s3Info:", s3Info)
        default:
            fmt.Printf("s3Info Type: %T\n", c)
    }
    // type assert to map
    s3Info := outputs[key].(map[string]interface{})
    fmt.Println("Key:", key, "=>", "s3Config:", s3Info["s3Config"])
}

The printout is as follows:

s3Info: [map[s3Config:map[bucket:testbucket-data s3Key:runs/6033fd684304200011ef3bc5/init/03a78d21-446a-41bc-b4c1-eb66e04f45e2/52c8a076-f6c4-4180-8625-38ca52482628] size:158971 type:s3 varType:File]]
s3Info Type: []interface {}
interface conversion: interface {} is []interface {}, not map[string]interface {}


Solution

  • The s3Info was unmarshalled by json.Unmarshal() into an array of interface{} but not a map. The contents inside can be retrieved through type assertion to []interface{}.

    s3Config can be obtained through:

    for _, s := range s3Info.([]interface{}) {
      s3Config := s.(map[string]interface{})["s3Config"]
    }
    

    Thanks @brits for the useful link: