I'm writing a Golang api and client but can't get valid json from a slice of structs in the api. The result I get in my client looks like this.
[{0 Mark 1234 false} {0 John 3456 false}]
I need this json to look like
[{"id":0, "name":Mark, "pin":1234, "active":false} {"id":0, "name":John, "pin":3456, "active":false}]
I can't find examples showing me how to code this properly and this is not a duplicate of anything I can find despite a warning that it is. While my client successfully parses the JSON back to a struct, I also need it to return JSON to an IOS client which is requesting it. The flow is API -> API -> iOS client. I don't know how to produce JSON from the struct for the iOS client.
Here is my api code.
// Employee model
type Employee struct {
EmployeeID int64 `json:"id"`
Name string `json:"name"`
Pin int `json:"pin"`
Active bool `json:"active"`
}
func getEmployees(db *sql.DB, venueID int64) ([]Employee, error) {
var employee Employee
var employees []Employee
query, err := db.Query("SELECT id, name, pin FROM employees WHERE active=1 AND venue_id=? ORDER BY name", venueID)
if err != nil {
return employees, err
}
defer query.Close()
for query.Next() {
err = query.Scan(&employee.EmployeeID, &employee.Name, &employee.Pin)
if err != nil {
return employees, err
}
employees = append(employees, employee)
}
return employees, err
}
func (rs *appResource) listEmployees(w http.ResponseWriter, r *http.Request) {
var venue Venue
token := getToken(r)
fmt.Println(token)
venue, err := getVenue(rs.db, token)
if err != nil {
log.Fatal(err)
return
}
venueID := venue.VenueID
if !(venueID > 0) {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
employees, err := getEmployees(rs.db, venueID)
if err != nil {
log.Fatal(err)
return
}
fmt.Println(employees[0].EmployeeID)
employeesJSON, err := json.Marshal(employees)
if err != nil {
log.Fatal(err)
return
}
w.Write([]byte(employeesJSON))
}
Here is my client code:
func (rs *appResource) getEmployees(w http.ResponseWriter, r *http.Request) {
path := rs.url + "/employees"
fmt.Println(path)
res, err := rs.client.Get(path)
if err != nil {
log.Println("error in get")
log.Fatal(err)
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
defer res.Body.Close()
if res.StatusCode == 500 {
fmt.Printf("res.StatusCode: %d
", res.StatusCode)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
if res.StatusCode == 404 {
fmt.Printf("res.StatusCode: %d
", res.StatusCode)
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatal(err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
// here I want to return actual JSON to an iOS client
w.WriteHeader(http.StatusOK)
w.Write([]byte("{ok}"))
}
What your code is currently printing is the content of a struct, not JSON. When you print the contents of a struct, by default, you will print just the values within that struct. That means that fmt.Println(employees.EmployeeList)
will produce something like:
[{0 Mark 1234 false} {0 John 3456 false}]
If you want to also print field values, you'll need to add a format 'verb' %+v
which will print field names. fmt.Printf("%+v ", employees.EmployeeList)
should print something like:
[{id:0 name:Mark pin:1234 active:false} {id:0 name:John pin:3456 active:false}]
I think what you actually want to look at doing is marshalling your data back into a JSON string again in order to write that content back out for the client.
I'm actually surprised that your code is running at all since you have 2 unused variables (err,err at listEmployees). any way that should work, added an fmt.Println so you will be able to see the result at the console
type Employee struct {
ID int `json:"id"`
Name string `json:"name"`
Pin int `json:"pin"`
Active bool `json:"active"`
}
func (rs *appResource) listEmployees(w http.ResponseWriter, r *http.Request) {
employees, _:= getEmployees(rs.db)
employeesJSON, _:= json.Marshal(employees)
fmt.Ptintln(string(employeesJSON))
w.Write(employeesJSON)
}
another run example:
func main() {
emp := Employee{
ID: 1,
Name: "Mark",
Pin: 1234,
Active: true,
}
if jsn, err := json.Marshal(emp); err == nil {
fmt.Println(string(jsn))
} else {
log.Panic(err)
}
}
type Employee struct {
ID int `json:"id"`
Name string `json:"name"`
Pin int `json:"pin"`
Active bool `json:"active"`
}
Output:
{"id":1,"name":"Mark","pin":1234,"active":true}
What you seem to want is a dump of the json, here you dump the struct, what you could do with the struct is to dump key and value with %+v in a Printf, have a look here : https://golang.org/pkg/fmt/#hdr-Printing.