#Access JSON elements from a POST call

19 messages · Page 1 of 1 (latest)

karmic canopy
#

Hello,

Still new-ish to golang but im trying to send a curl to an auth/login endpoint for an API and retrieve back a token. This is what I have so far:

func FetchToken() string {
    client := &http.Client{}
    var data = strings.NewReader(`grant_type=&username=<username>&password=<password>&scope=&client_id=&client_secret=`)
    req, err := http.NewRequest("POST", "<url>", data)
    if err != nil {
        panic(err)
    }
    req.Header.Set("accept", "application/json")
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    bodyText, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    return string(bodyText)
}

The expected output is something like:

{
  "ChallengeParameters": {},
  "AuthenticationResult": {
    "AccessToken": "<token>",
    "ExpiresIn": 3600,
    "TokenType": "Bearer",
  "ResponseMetadata": {
    "RequestId": "<id>",
    "HTTPStatusCode": 200,
    "HTTPHeaders": {
      "date": "Wed, 22 Nov 2023 19:02:22 GMT",
      "content-type": "application/x-amz-json-1.1",
      "content-length": "4294",
      "connection": "keep-alive",
      "x-amzn-requestid": "<id>"
    },
    "RetryAttempts": 0
  }
}

When I get a successful payload back with the token, how do I need to change my function code to basically do this:

token := FetchToken()
fmt.printf("%v", token.AuthenticationResult.AccessToken)
lusty moat
#

encoding/json.Unmarshal is what you are looking for

#

and use quicktype to generate types for your json response

#

Additionally, I would suggest not to use panic in your code but return errors as last parameter from your function.

karmic canopy
#

Ok give me one second

karmic canopy
# lusty moat https://gobyexample.com/json

ok taking a look at these examples, i don't think there's any that fit my needs. A lot of these you declare a struct and then instantiate it with some values. In my use case i'm POSTing to an authentication endpoint, and its supposed to return back to me the values.

I've got the struct defined already for the response body

lusty moat
#

can you post your updated code

#

you would do something like this:

var token GeneratedTokenStruct
err := json.Unmarshal(data, &token)
if err != nil {
    return "", err
}
return token.AuthenticationResult.AccessToken, nil
karmic canopy
#

yeah I think i'm on the same track. Do I have to do this too? var response map[string]interface{}

lusty moat
#

if you don't need all of the other response values, you can also simply remove all of the unneeded fields from your generated struct(s)

karmic canopy
#

yeah I don't need them all I'm just looking for the token

lusty moat
#

preferrably avoid interface{}

karmic canopy
#

and then I need to replace GeneratedTokenStruct in your example with my struct name I created?

lusty moat
#
type TokenResponse struct {
    AuthenticationResult AuthenticationResult `json:"AuthenticationResult"`
}

type AuthenticationResult struct {
    AccessToken string `json:"AccessToken"`
}
#

that's like the minimal number of types you need

#

an then you'd replace GeneratedTokenStruct with TokenResponse and you are done

karmic canopy
#

ok im gonna test real quick