Skip to content
This repository has been archived by the owner on Jul 29, 2020. It is now read-only.

Add csv renderer #17

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions csv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package middlewares

import (
"bytes"
"encoding/json"
"sort"
"strconv"
"strings"
)

func csvFromJSON(b []byte) (result []byte, err error) {
var data []map[string]interface{}
err = json.Unmarshal(b, &data)
if err != nil {
return
}
if len(data) == 0 {
return
}
keys := make([]string, 0, len(data[0]))
for k := range data[0] {
keys = append(keys, k)
}
sort.Strings(keys)
var strOut bytes.Buffer
line := strings.Join(keys, ";") + "\n"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're writing csv on hand, there's the encoding/csv[1] package to do that job

[1] https://golang.org/pkg/encoding/csv/

strOut.WriteString(line)
for _, v := range data {
values := decodeLine(keys, v)
line := strings.Join(values, ";") + "\n"
strOut.WriteString(line)
}
return strOut.Bytes(), nil
}

func decodeLine(keys []string, data map[string]interface{}) []string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encoding/csv does this job for you
https://golang.org/src/encoding/csv/writer.go#L48

values := make([]string, 0, len(data))
for _, k := range keys {
v := data[k]
switch vv := v.(type) {
case map[string]interface{}:
values = append(values, "nil")
case string:
vv = `"` + strings.ReplaceAll(vv, `"`, " ") + `"`
values = append(values, vv)
case float64:
values = append(values, strconv.FormatFloat(vv, 'f', -1, 64))
case []interface{}:
values = append(values, "nil")
case bool:
values = append(values, strconv.FormatBool(vv))
default:
values = append(values, "nil")
}
}
return values
}
12 changes: 12 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ func renderFormat(w http.ResponseWriter, recorder *httptest.ResponseRecorder, fo
m := make(map[string]string)
m["error"] = strings.TrimSpace(string(byt))
byt, _ = json.MarshalIndent(m, "", "\t")
if format == "csv" {
format = "json"
}
}
switch format {
case "xml":
Expand All @@ -64,6 +67,15 @@ func renderFormat(w http.ResponseWriter, recorder *httptest.ResponseRecorder, fo
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(recorder.Code)
w.Write([]byte(xmlStr))
case "csv":
result, err := csvFromJSON(byt)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(recorder.Code)
w.Write(result)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error return value of w.Write is not checked (from errcheck)

default:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(recorder.Code)
Expand Down