How to iterate over an []interface{} in Go
Asked Answered
D

2

10

I'm struggling to get the keys and values of the following interface, which is the result of JSON marshaling the result returned by Execute as demonstrated in this example:

[
    [
        {
            "id": 36,
            "label": "TestThing",
            "properties": {
                "schema__testBoolean": [
                    {
                        "id": 40,
                        "value": true
                    }
                ],
                "schema__testInt": [
                    {
                        "id": 39,
                        "value": 1
                    }
                ],
                "schema__testNumber": [
                    {
                        "id": 38,
                        "value": 1.0879834
                    }
                ],
                "schema__testString": [
                    {
                        "id": 37,
                        "value": "foobar"
                    }
                ],
                "uuid": [
                    {
                        "id": 41,
                        "value": "7f14bf92-341f-408b-be00-5a0a430852ee"
                    }
                ]
            },
            "type": "vertex"
        }
    ]
]

A reflect.TypeOf(result) results in: []interface{}.

I've used this to loop over the array:

s := reflect.ValueOf(result)
for i := 0; i < s.Len(); i++ {
  singleVertex := s.Index(i).Elem() // What to do here?
}

But I'm getting stuck with errors like:

reflect.Value.Interface: cannot return value obtained from unexported field or method

Discharge answered 4/7, 2018 at 11:26 Comment(3)
If there is no requirement to use reflection then you should avoid it and loop over the []interface{}.Transport
So, I would only use reflection if I don't know the structure?Discharge
@BobvanLuijt: Basically.Delimitate
D
12

If you know that's your data structure, there's no reason to use reflection at all. Just use a type assertion:

for key, value := range result.([]interface{})[0].([]interface{})[0].(map[string]interface{}) {
    // key == id, label, properties, etc
}
Delimitate answered 4/7, 2018 at 11:29 Comment(0)
T
6

For getting the underlying value of an interface use type assertion. Read more about Type assertion and how it works.

package main

import (
    "fmt"
)

func main() {
     res, err := g.Execute( // Sends a query to Gremlin Server with bindings
           "g.V(x)",
            map[string]string{"x": "1234"},
            map[string]string{},
     )
     if err != nil {
          fmt.Println(err)
          return
     }
     fetchValue(res)
}

func fetchValue(value interface{}) {
    switch value.(type) {
    case string:
        fmt.Printf("%v is an interface \n ", value)
    case bool:
        fmt.Printf("%v is bool \n ", value)
    case float64:
        fmt.Printf("%v is float64 \n ", value)
    case []interface{}:
        fmt.Printf("%v is a slice of interface \n ", value)
        for _, v := range value.([]interface{}) { // use type assertion to loop over []interface{}
            fetchValue(v)
        }
    case map[string]interface{}:
        fmt.Printf("%v is a map \n ", value)
        for _, v := range value.(map[string]interface{}) { // use type assertion to loop over map[string]interface{}
            fetchValue(v)
        }
    default:
        fmt.Printf("%v is unknown \n ", value)
    }
}
Transport answered 4/7, 2018 at 12:0 Comment(3)
It is just an example my main concern was to unmarshal and then use type assertion to get the underlying value. I m just using recursion to get the value of slice of interface{}. I have used json as an example Since OP has given the json in his question.Transport
The OP has explained that his result variable is the output of the Execute method, which does not return, nor consume, JSON. Perhaps the data in the database is stored as JSON, but it is not accessible in that form via the Go client library, so answering with json.Unmarshal is a non-answer.Delimitate
Ok but using recursion to fetch the value of slice of interface{} can be done in any case. So I am edited my answer according to you thanks for infromation.Transport

© 2022 - 2024 — McMap. All rights reserved.