Golang json marshal and encoding give weird output

Issue

I am trying to customise error message for my db query . Following is what I am doing first I create struct Errormessage . Next if there is error in db.query I do this marshaling then encoding and return. But I end up getting this output "e30=" on my postman testing. What could be wrong I check and followed few examples are showing this mechanism ?

 error1 := Errormessage{"Error in select"}
        error1_enc,errEn := json.Marshal(error1)
        if errEn != nil {
                
          // if error is not nil
          // print error
          fmt.Println(errEn)
      }
        json.NewEncoder(w).Encode(error1_enc)
            return

/

/ declaring a struct
type Errormessage struct{
        
  // defining struct variables
  errormessage string
}
func checkExistUser(w http.ResponseWriter, r *http.Request) {
 
  r.ParseForm()
  fmt.Println("File Name :", r.FormValue("email"))

  result, err := db.Query("SELECT * from userDetailsss")
  if err != nil {
    //http.Error(w, err, 500)
    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    w.Header().Set("X-Content-Type-Options", "nosniff")
    w.WriteHeader(400)
    fmt.Println(err)
    error1 := Errormessage{"Error in select"}
    error1_enc,errEn := json.Marshal(error1)
    if errEn != nil {
            
      // if error is not nil
      // print error
      fmt.Println(errEn)
  }
    json.NewEncoder(w).Encode(error1_enc)
        return
    //panic(err.Error())
  }

// This part is how my db is defined and opened

var db *sql.DB
var err error

func main() {
  db, err = sql.Open("mysql", "******#@tcp(127.0.0.1:3306)/****")
  if err != nil {
    panic(err.Error())
  }
  defer db.Close()
  router := mux.NewRouter()
  router.HandleFunc("/", DoHealthCheck).Methods("POST")
  router.HandleFunc("/checkExistUser", checkExistUser).Methods("POST")
  log.Fatal(http.ListenAndServe(":8080", router))
  
}

Solution

There are two issues with your code:

  1. You are json encoding the already json encoded error. This means that you are json encoding raw json bytes, which is the reason for the weird output.
  2. Your Errormessage struct’s field is unexported. Unexported fields will not be encoded by the encoding/json package.

To fix #1 you can do:

func checkExistUser(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    fmt.Println("File Name :", r.FormValue("email"))

    result, err := db.Query("SELECT * from userDetailsss")
    if err != nil {
        w.Header().Set("Content-Type", "application/json; charset=utf-8")
        w.Header().Set("X-Content-Type-Options", "nosniff")
        w.WriteHeader(400)
        
        // use only Encode, no need to call json.Marshal
        if err := json.NewEncoder(w).Encode(Errormessage{"Error in select"}); err != nil {
            log.Println("failed to send reposnse:", err)
        }
        return
    }
    
    // ...
}

To fix #2 you can do:

type Errormessage struct {
    // export the field, i.e. change it to start with an upper case letter
    Errormessage string `json:"errormessage"`
}

Answered By – mkopriva

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.