1

I'm trying to decode dynamic/random JSON responses in GO, with nested data

    body, _ := ioutil.ReadAll(response.Body)
    resp := make(map[string]interface{})
    err = json.Unmarshal(body, &resp)

    fmt.Printf("BODY: %T<\n", body)
    fmt.Printf("BODY: %s<\n", body)
    fmt.Printf("RESP: %s<\n", resp)
    fmt.Printf("RESP: %T<\n", resp)
    fmt.Printf("RESP[results]: %T<\n", resp["results"])
    fmt.Printf("RESP[results]: %s<\n", resp["results"])

body is the JSON result from the HTTP server and I unmarshall it and the result looks to be a slice of bytes.

BODY: []uint8

BODY: {"results":[{"code":500.0,"errors":["Configuration file 'c2-web-2.conf' already exists."],"status":"Object could not be created."}]}

So I unmarshall it into resp and that works as expected.

RESP: map[string]interface {}

RESP: map[results:[map[code:%!s(float64=500) errors:[Configuration file 'c2-web-2.conf' already exists.] status:Object could not be created.]]]<

I'm able to access the map with the key results.

RESP[results]: []interface {}

RESP[results]: [map[code:%!s(float64=500) errors:[Configuration file 'conf.d/hosts/c2-web-2.conf' already exists.] status:Object could not be created.]]<

Now what i want to access it the "code", "errors" and "status" which is in resp["results"] This looks like an array or slice and I've tried indexing it but I get the error at compile time

./create_host.go:62: invalid operation: resp["results"][0] (type interface {} does not support indexing)

I've done a lot of googling, tried unmarshalling the data within resp["results"] etc, but after a few days I have not made much progress.

How should I access the map which seems to be a member of an array? The data structure is not guaranteed so I can't create a structure and unmarshall into that.

Thanks

2 Answers 2

2

A co-worker provided the code fragement below which made it possible to access the map entries I was looking for.

    respBody, _ := ioutil.ReadAll(response.Body)

    var rsp interface{}
    if err := json.Unmarshal(respBody, &rsp); err != nil {
            log.Fatal(err)
    }
    resultMap := rsp.(map[string]interface{})["results"].([]interface{})[0].(map[string]interface{})
    fmt.Printf("test: %s<\n", resultMap["errors"] )

test: [Configuration file 'c2-web-2.conf' already exists.]<

Sign up to request clarification or add additional context in comments.

Comments

1

I believe you need to do a type assertion. You have an interface{}, but you need some sort of slice to index into. Try resp["results"].([]interface{})[0]? (Sorry, haven't had a chance to test this myself.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.