我有以下要求:REST API以以下格式返回错误:
Error format
422
{
"name-of-field": [
"can't be blank",
"is too silly"
]
}
我的代码如下:
var PostFeedback = func(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
surveyId := params["id"]
feedback := &models.Feedback{}
err := json.NewDecoder(r.Body).Decode(feedback)
if err != nil {
jsonError := fmt.Sprintf(`{
"%s": [
"%s"
]
}`, "errors", err)
log.Printf("invalid input format, %v", jsonError)
resp := map[string]interface{}{"error": jsonError}
u.Respond(w, resp)
return
}
问题:
如何获取违规字段的名称?
我如何最好地满足要求?
答案 0 :(得分:1)
encoding/json
软件包不提供对“空白”或“傻”值的验证。仅当主体中的数据不是有效的json时,或者如果JSON中的字段类型(根据包的规范)与结构的字段类型不匹配时,它才会返回错误。您正在尝试解码该json。
第一种错误类型为json.SyntaxError
,如果您得到此错误,则不一定总能满足您的要求,因为可能没有 no 个实际字段可用于响应,或者如果存在json字段,则它们及其值可能是完全有效的json,但错误的原因可能出在其他地方(请参见example)。
如果数据包含实际的json字段,但是具有非json值,则可以使用Offset
类型的SyntaxError
字段在数据中找到最接近的前一个字段流。使用strings.LastIndex
,您可以实施天真解决方案以向后查找该字段。
data := []byte(`{"foobar": i'm not json}`)
err := json.Unmarshal(data, &T{})
se, ok := err.(*json.SyntaxError)
if !ok {
panic(err)
}
field := string(data[:se.Offset])
if i := strings.LastIndex(field, `":`); i >= 0 {
field = field[:i]
if j := strings.LastIndex(field, `"`); j >= 0 {
field = field[j+1:]
}
}
fmt.Println(field) // outputs foobar
注意:如您所见,为了能够查找字段,您需要有权访问数据,但是当您使用json.NewDecoder
并传递时如果它直接位于请求的正文中,而无需先将其内容存储在某个地方,则在完成解码器的Decode
方法后,您将无法访问该数据。这是因为正文是包裹在io.ReadCloser
中的字节流,它不支持“倒带”,即您不能 re-read 解码器已经读取的字节。为避免这种情况,您可以使用ioutil.ReadAll
读取正文的全部内容,然后使用json.Unmarshal
进行解码。
第二种错误类型为json.UnmarshalTypeError
。如果查看错误类型及其字段的文档,您将知道您所要做的就是键入断言返回的值,然后就完成了。 Example
在将json成功解码到您的结构后,将对“空白”和“傻”值进行验证。您的操作方式取决于您。例如,您可以使用专为验证结构而设计的第三方软件包,也可以自己实施内部解决方案,等等。我实际上对哪个是“最佳”一事没有意见,因此我可以帮你解决这个问题。
我能说的是,最基本的方法是简单地查看结构的每个字段,并根据该字段的要求检查其值是否有效。
>