0

I have a Gin-Gonic REST API in Golang. Here I am trying to output users that are already registered as JSON, currently in Postman I only get that:

(You can ignore the lastRequest-Attribut, because it is currently always nil)

"[{\"id\":\"e61b3ff8-6cdf-4b23-97a5-a28107c57543\",\"firstname\":\"John\",\"lastname\":\"Doe\",\"email\":\"[email protected]\",\"username\":\"johndoe\",\"token\":\"19b33c79-32cc-4063-9381-f2b64161ad8a\",\"lastRequest\":null},

But I want it like this:

[{
        "id": "e61b3ff8-6cdf-4b23-97a5-a28107c57543",
        "username": "johndoe",
        "email": "[email protected]",
        "token": "19b33c79-32cc-4063-9381-f2b64161ad8a",
        "lastRequest": null
    }]

How do I manage this, I tried many things with the 'json.MarshalIndent' (from this stackoverflow-post), however it didn't change anything for me, what do I need to do? Because the backslashes stay no matter what I do, at most \t or spaces are inserted. I have also read that I have to do it as a byte array, but that didn't work for me either (maybe I did something wrong here too).

Here my current code:


var users []User
r.GET("/getusers", func(c *gin.Context) {
    usersArr := make([]User, len(users))
    for i := 0; i < len(users); i++ {
        usersArr[i] = users[i]
    }
        
    userJson, err := json.Marshal(testUser)
    if err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
    } else {
        c.JSON(200, string(userJson))
    }
})

type User struct {
    Id          string        `json:"id"`
    Firstname   string        `json:"firstname"`
    Lastname    string        `json:"lastname"`
    Email       string        `json:"email"`
    Username    string        `json:"username"`
    Token       string        `json:"token"`
    LastRequest []lastRequest `json:"lastRequest"`
}

2
  • c.JSON does the encoding for you, so you are double encoding by calling json.Marshal. Commented Apr 18, 2022 at 9:55
  • @Peter Yes I noticed that too, do you have a solution? Commented Apr 18, 2022 at 10:28

3 Answers 3

1

Two things:

  1. The "backslashes" are just escape characters. They aren't literally there.
  2. Indenting JSON is a simple matter of calling the appropriate Indent function:

If you have the JSON string already, use the json.Indent function from the encoding/json package:

input := []byte("[{\"id\":\"e61b3ff8-6cdf-4b23-97a5-a28107c57543\",\"firstname\":\"John\",\"lastname\":\"Doe\",\"email\":\"[email protected]\",\"username\":\"johndoe\",\"token\":\"19b33c79-32cc-4063-9381-f2b64161ad8a\",\"lastRequest\":null}]")
buf := &bytes.Buffer{}
if err := json.Indent(buf, input, "", "\t"); err != nil {
    panic(err)
}
fmt.Println(buf.String())

Playground link

However, if you're trying to marshal directly into the indented form, just use the MarshalIndent function intead of Marshal:

    userJson, err := json.MarshalIndent(testUser, "", "\t")
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the reply, I have tested both options but it does not work for me. Option 1 usersArr := make([]User, len(users)) userJson, err := json.Marshal(usersArr) buf := &bytes.Buffer{} if err := json.Indent(buf, userJson, "", "\t"); err != nil { // err } else { c.JSON(200, buf.String()) } Option 2 usersArr := make([]User, len(users)) userJson2, err := json.MarshalIndent(usersArr, "", "\t") if err != nil { // err } else { c.JSON(200, string(userJson2)) } Result 1 + 2 "[\n\t{\n\t\t\"id\": \"db848d0e-8f7f-434f-bf6d-fd9085c9c86f\ ...
In the console the JSON is formatted pretty, but in postman there is the same problem. userJson, err := json.Marshal(usersArr) input := []byte(userJson) if err != nil { c.JSON(400, gin.H{"error-name": "userArray is empty (nil)", "error-message": err.Error()}) } else { buf := &bytes.Buffer{} if err := json.Indent(buf, input, "", "\t"); err != nil { c.JSON(400, gin.H{"error": err.Error()}) } c.JSON(200, buf.String()) fmt.Println(buf.String()) }
That shows that it is working. The \t characters are tabs.
But why is it not formatted when I make a request with postman or curl? It is only formatted when it is directly output to the console, but I would need it in the request.
0

Well this would be my first answer in stackoverflow, hope this helps.

Go gin framework comes with a few handy functions, since I've got no idea what version of golang nor Gin Framework you're using you could try this:

var users []User
r.GET("/getusers", func(c *gin.Context) {
    usersArr := make([]User, len(users))
    for i := 0; i < len(users); i++ {
        usersArr[i] = users[i]
    }
        
    if err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
    } else {
        c.JSON(200, users)
// If Indentation is required you could try:
        c.IndentedJSON(200, users)
    }
})

type User struct {
    Id          string        `json:"id"`
    Firstname   string        `json:"firstname"`
    Lastname    string        `json:"lastname"`
    Email       string        `json:"email"`
    Username    string        `json:"username"`
    Token       string        `json:"token"`
    LastRequest []lastRequest `json:"lastRequest"`
}

Comments

0

Hope this function helps.

import (
"encoding/json"
"strings"
)

func logRequest(log *logrus.Entry, data []byte) {
        cp := bytes.NewBuffer([]byte{})
        if err := json.Compact(cp, data); err == nil {
            log.Info("Request received: ", string(cp.Bytes()))
        } else {
            stringifiedData := strings.Replace(string(data[:]), "\n", "", -1)
            stringifiedData = strings.Replace(stringifiedData, "\r\n", "", -1)
            stringifiedData = strings.Replace(stringifiedData, "\t", "", -1)
            log.Info("Request received: ", strings.ReplaceAll(stringifiedData, " ", ""))
        }
    }

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.