Go JSON to Vue front end has issues

25 Views Asked by At

I have an existing application that I wrote that uses Go, MongoDB, and Vue.js. I was written to run locally. I am converting it to use AWS lambda, Atlas MongoDB (hosted on AWS) and VueJS on the front.

The lambda seems to work correctly (fetches documents from MongoDB) and I convert them to JSON. The slice of documents (pointers) are converted using json.marshal (which returns bytes[]) and then converted to a string.

log.Println("Getting all MBs")
    mbs, err := getAllMBs()
    if err != nil {
        log.Println(err)
        return nil, err
    }

    j, err := json.Marshal(mbs)
    s := string(j)

    log.Println()

    if err != nil {
        log.Println(err)
        return nil, err
    }
    headers := map[string]string{
        "Access-Control-Allow-Origin": "*",
        "Content-Type":                "application/json",
    }

    return map[string]interface{}{
        "statusCode": 200,
        "headers":    headers,
        "body":       s,
    }, nil


In the vuejs I use axios to fetch the response. I access the json string by using response.data.body. (see map returned from Go lambda) However the javascript treats the resulting information as one big string. Previously I had looped through the array and used convert object to create the js model object(s).

async getAllMBs(){
        // // eslint-disable-next-line no-debugger
        // debugger
          // CHANGED
          await this.$http.get("https://xsp15b9d2k.execute-api.us-east-1.amazonaws.com/prod/getAllMBs").then(response =>{
       // await this.$http.get("/getAllMilkBottles").then(response => {
          let mbs = response.data.body

            console.log(mbs)
            let mb = []
          if(mbs){
            this.milkBottles =[];
            this.searchMilkBottles = [];
            //console.log(mbs.length)
            for(let idx = 0;idx < mbs.length;idx++){
              mb[idx] = MilkBottle.convertObject(mbs[idx])
               //console.log(mbs[idx])
              this.milkBottles.push(mb[idx])
              this.searchMilkBottles.push(mb[idx])
            }
          }else{
            console.log("help")
          }
          this.error = ""
        }).catch(err=> {
              console.log(err)
              //this.setError();
            }
        )
      }

In the original application I did not need to create a map in Go.

1

There are 1 best solutions below

0
Jim Wright On BEST ANSWER

Your lambda is json encoding twice, so data is actually a JSON encoded array.

{
  "data": "[{\"id\":\"1\",\"url\":\"/images/bottle-of-milk-science-photo-library.jpg\",\"city\":\"Sellersville\",\"county\":\"PA\",\"state\":\"PA\",\"name\":\"MICHAEL S CLOVIS\",\"cost\":\"0\",\"wanted\":\"0\"}]",
  "headers": {
    "Access-Control-Allow-Origin": "*",
    "Content-Type": "application/json"
  },
  "statusCode": 200
}

It looks like you can just skip the json encoding on mbs, as you're already json encoding the entire map, or lambda is doing it for you based on the Content-Type header.

    log.Println("Getting all MBs")
    mbs, err := getAllMBs()
    if err != nil {
        log.Println(err)
        return nil, err
    }
    headers := map[string]string{
        "Access-Control-Allow-Origin": "*",
        "Content-Type":                "application/json",
    }

    return map[string]interface{}{
        "statusCode": 200,
        "headers":    headers,
        "body":       mbs,
    }, nil

That should mean your lambda response is a single json object, and data doesn't need to be decoded anymore.

{
  "data": [
    {
      "id": "1",
      "url": "/images/bottle-of-milk-science-photo-library.jpg",
      "city": "Sellersville",
      "county": "PA",
      "state": "PA",
      "name": "MICHAEL S CLOVIS",
      "cost": "0",
      "wanted": "0"
    }
  ],
  "headers": {
    "Access-Control-Allow-Origin": "*",
    "Content-Type": "application/json"
  },
  "statusCode": 200
}