Home > other >  AWS EventBridge PutEvent Detail Malformed
AWS EventBridge PutEvent Detail Malformed

Time:03-05

I have tried both AWS Go SDKs both versions and every time I get an error stating that the Details field is malformed. The Details field accepts a JSON string.

In SDK V2 you basically have a struct for the event

type Event struct {
Details []struct {
    Key   string `json:"Key"`
    Value string `json:"Value"`
} `json:"Details"`
DetailType string `json:"DetailType"`
Source     string `json:"Source"`

}

The example then builds up the JSON string with this code

myDetails := "{ "
for _, d := range event.Details {
    myDetails = myDetails   "\""   d.Key   "\": \""   d.Value   "\","
}

myDetails = myDetails   " }"

And then make the api call

input := &cloudwatchevents.PutEventsInput{
    Entries: []types.PutEventsRequestEntry{
        {
            Detail:     &myDetails,
            DetailType: &event.DetailType,
            Resources: []string{
                *lambdaARN,
            },
            Source: &event.Source,
        },
    },
}

Basically I get an error saying that the string assigned to the Detail field is malformed. I believe this is because the example code generates a string with a trailing which is not valid . However when you omit the , you get a nil memory reference.

AWS SDK Example

The example for SDK version 1 also generates an error.
Any help would be great

CodePudding user response:

The code on the page you linked is not 100% correct. They actually link the "complete example" at the bottom of the page, which has slightly different code:

https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/gov2/cloudwatch/PutEvent/PutEventv2.go#L108-L117

myDetails := "{ "
for i, d := range event.Details {
    if i == (len(event.Details) - 1) {
        myDetails = myDetails   "\""   d.Key   "\": \""   d.Value   "\""    
    } else {
        myDetails = myDetails   "\""   d.Key   "\": \""   d.Value   "\","
    }
}

myDetails = myDetails   " }"

But building the JSON like this is not ideal and error-prone, as you already found out.

I'd propose the following:

details := make(map[string]string, len(event.Details))
for _, d := range event.Details {
    details[d.Key] = d.Value
}

b, err := json.Marshal(details)
if err != nil {
    return
}

fmt.Println(string(b))

Checkout the playground to see it in action:

https://play.golang.com/p/E4ueZLGIKp4

  • Related