8

I have array of a struct being created from data I collected from the database.

For simplicity, lets say this is the struct:

type Person struct {
ID        int    `db:"id, json:"id"`
}

type PessoalController struct{}

func (ctrl PessoalController) GetPessoal(c *gin.Context) { 
    q := "select id from rh"

    rows, err := db.GetDB().Query(q)
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    var pessoas []Pessoal

    var id
    for rows.Next() {
        err := rows.Scan(&id)
        if err != nil {
            log.Fatal(err)
    }
    pessoas = append(pessoas, Pessoal{ ID: id,})

    JsonPessoal, errr := json.Marshal(pessoas)
    if errr != nil {
        log.Fatal(err)
    }
    c.JSON(200, pessoas)
    if err != nil {
        return
    }

    return
}

When I print it, I do get the JSON I expected. But when I send the response, I get raw-looking data like “W3siWQiQjlyNDYslNpYx...”

Have no idea how to proceed.

Edit : Minimal, Complete, and Verifiable example.

Auyer
  • 2,693
  • 3
  • 15
  • 32
  • Please show a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). As is, `err` is never assigned, and we don't know what `c.JSON` is. – Marc Dec 28 '17 at 16:34
  • 1
    BTW that "raw-looking data" looks like base64-encoded to me. And its first bytes actually decode to `[{"` FWIW… – kostix Dec 28 '17 at 18:25
  • Thanks for the input @Marc and kostix, I've corrected the exemple. – Auyer Jan 05 '18 at 11:48

2 Answers2

20

c.JSON is serializing into JSON, so you should be doing:

c.JSON(200, pessoas)
dave
  • 62,300
  • 5
  • 72
  • 93
  • What is `c.JSON`, after all? – kostix Dec 28 '17 at 18:25
  • 1
    @kostix In case you really want to know, it's most probably this: https://godoc.org/github.com/gin-gonic/gin#Context.JSON. – mkopriva Dec 28 '17 at 19:38
  • @Rafael `c.JSON` makes it easier for data to be respond in JSON. You can still use response writer but you have to manually add the JSON response header and all. – sh0umik Dec 30 '17 at 23:37
4

Your codes ans the question itself. Look at it and read my comments in the code.

jsonPessoal, errr := json.Marshal(pessoas)
if errr != nil {
    log.Fatal(err)
}
fmt.Fprintf(os.Stdout, "%s", jsonPessoal) // still fine here .
// it is fine because you are formating []byte into string using fmt and 
// printing it on console. `%s` makes sures that it echos as string. 

c.JSON(200, jsonPessoal ) // jsonPessoal is still a []byte !! 
if err != nil {
    return
}

The correct way to echo json string using gin would be

c.JSON(http.StatusOK, gin.H{ 
            "code" : http.StatusOK, 
            "message": string(jsonPessoal),// cast it to string before showing
})
sh0umik
  • 1,549
  • 2
  • 17
  • 27
  • Thanks for the answer, but I was curious: Why is that you also return the status in the JSON body if the status is already in the header? Is it just for good practice / convention ? I'm interested in your answer. – Auyer Jan 05 '18 at 11:54
  • @RafaelAuyer The header is must but if you return the code in the body, that might help in some cause like for all 200+ request that is all valid but has different use. Like if you are using old Jquery and your response from api returns a 201 then that goes to success call back just like 200. Then you can use the code in the body to show different messge like, Your Resource is Created. Its a personal choice, I use this practise when I design any api. You can skip it if you want. – sh0umik Jan 05 '18 at 16:59