的error
類型是具有單個Error()
方法的接口,但它不是特殊的json
包(Error()
方法不被調用就可以了)。
但是,error
值可能包含靜態類型的值,這些值可能是很好的編碼,或者他們可以通過執行json.Marshaler
來定義自己的編組邏輯。通過調用Error()
方法簡單地將error
轉換爲string
意味着我們不尊重自定義編組邏輯。
所以我建議建立我們自己的錯誤切片類型上,我們可以實現這應該是我們的編組邏輯:
- 檢查,如果誤差值實現
json.Marshaler
,如果是的話,讓它元帥本身
- 否則作爲備用的情況下調用
error.Error()
以「獲得」 string
它可以很容易地封
這怎麼可能是這樣的:
type JSONErrs []error
func (je JSONErrs) MarshalJSON() ([]byte, error) {
res := make([]interface{}, len(je))
for i, e := range je {
if _, ok := e.(json.Marshaler); ok {
res[i] = e // e knows how to marshal itself
} else {
res[i] = e.Error() // Fallback to the error string
}
}
return json.Marshal(res)
}
而且這是你如何使用它:
err := person.Validate()
c.JSON(422, gin.H{"errors" : JSONErrs(err)})
讓我們來測試我們的JSONErrs
。我們還用它實現自定義編組邏輯自定義錯誤類型:
type MyErr struct{ line int }
func (me MyErr) Error() string { return "Invalid input!" }
func (me MyErr) MarshalJSON() ([]byte, error) {
return json.Marshal(
struct {
Type, Error string
AtLine int
}{"MyErr", me.Error(), me.line})
}
並測試代碼:
errs := []error{
errors.New("first"),
errors.New("second"),
MyErr{16},
}
data, err := json.Marshal(JSONErrs(errs))
fmt.Println(string(data), err)
輸出(嘗試在Go Playground):
["first","second",{"Type":"MyErr","Error":"Invalid input!","AtLine":16}] <nil>