/
json.go
129 lines (102 loc) · 2.42 KB
/
json.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package gowork
import (
"encoding/json"
"fmt"
validator "gopkg.in/validator.v2"
"net/http"
"reflect"
"bytes"
)
type Message struct {
Message string `json:"msg"`
}
type ErrorResponse struct {
Errors []Error `json:"errors"`
Count int `json:"count"`
}
func (er * ErrorResponse) Add(error Error) {
er.Errors = append(er.Errors, error)
er.Count++
}
type Error struct {
Field string `json:"field,omitempty"`
Message string `json:"msg"`
Index int `json:"index,omitempty"`
}
type IndexedError struct {
Err error
Index int
}
func (e IndexedError) Error() string {
return fmt.Sprintf("%d: %s", e.Index, e.Err.Error())
}
func WriteJSON(w http.ResponseWriter, data interface{}) {
b, err := json.MarshalIndent(data, "", " ")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
str := string(b)
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, str)
return
}
func WriteMessageToJSON(w http.ResponseWriter, message string) {
data := &Message{Message: message}
WriteJSON(w, data)
return
}
func WriteErrorToJSON(w http.ResponseWriter, code int, err interface{}) {
resp := &ErrorResponse{}
errorType := reflect.ValueOf(err)
switch errorType.Kind() {
case reflect.Slice:
m := err.([]error)
for _, v := range m {
formatError(v, resp)
}
default:
formatError(err, resp)
}
w.WriteHeader(code)
WriteJSON(w, resp)
return
}
func JSONResponse(w http.ResponseWriter, data interface{}, err interface{}) {
if _, ok := err.(NotFoundError); ok {
WriteErrorToJSON(w, http.StatusNotFound, err)
return
}
if err != nil {
WriteErrorToJSON(w, http.StatusInternalServerError, err)
return
}
WriteJSON(w, data)
}
func formatError(err interface{}, resp *ErrorResponse) {
index := 0
if e, ok := err.(IndexedError); ok {
index = e.Index
err = e.Err
}
if e, ok := err.(validator.ErrorMap); ok {
for k, v := range e {
resp.Add(Error{Field: k, Message: v.Error(), Index: index})
}
return
}
if e, ok := err.(error); ok {
resp.Add(Error{Message: e.Error(), Index: index})
return
}
resp.Add(Error{Message: fmt.Sprintf("%s", err), Index: index})
}
//FormatJSON is a quick utility method to format JSON. Primarily used in logging/testing as it doesn't return an error on failure.
func FormatJSON(src string) string {
dst := &bytes.Buffer{}
s := []byte(src)
if err := json.Indent(dst, s, "", " "); err != nil {
return err.Error()
}
return dst.String()
}