一年多前,GoOffset向类型添加了一个值(请参阅此处json.UnmarshalTypeError已关闭的问题以了解上下文)。偏移值背后的目的是有道理的,但我不确定在读取类型为 的 go http 响应正文时如何使用它。io.ReadCloser
// An UnmarshalTypeError describes a JSON value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError struct {
Value string // description of JSON value - "bool", "array", "number -5"
Type reflect.Type // type of Go value it could not be assigned to
Offset int64 // error occurred after reading Offset bytes
}
Run Code Online (Sandbox Code Playgroud)
例如:
var body CustomType
decoderErr := json.NewDecoder(response.Body).Decode(&body)
if decoderErr != nil {
if typeError, ok := decoderErr.(*json.UnmarshalTypeError); ok {
// Do something with typeError.Offset here
}
}
Run Code Online (Sandbox Code Playgroud)
在捕获错误时,我已经从response.Bodyvia读取了内容json.NewDecoder...。我正在寻找一种response.Body再次读取的方法,但只能通过使用 typeError 中的 Offset 值来读取错误点。
由于您想重用请求正文,因此您应该在解组正文之前读取并存储正文,然后如果存在 JSON 语法或类型错误,您可以使用之前存储的正文返回更有用的错误。
概念证明:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type Hello struct {
Name string `json:"name"`
Message string `json:"message"`
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading body", 400)
return
}
h := &Hello{}
if err := json.Unmarshal(b, &h); err != nil {
var msg string
switch t := err.(type) {
case *json.SyntaxError:
jsn := string(b[0:t.Offset])
jsn += "<--(Invalid Character)"
msg = fmt.Sprintf("Invalid character at offset %v\n %s", t.Offset, jsn)
case *json.UnmarshalTypeError:
jsn := string(b[0:t.Offset])
jsn += "<--(Invalid Type)"
msg = fmt.Sprintf("Invalid value at offset %v\n %s", t.Offset, jsn)
default:
msg = err.Error()
}
http.Error(w, msg, 400)
return
}
w.Write([]byte(`Good to go!`))
})
if err := http.ListenAndServe(":8000", nil); err != nil {
log.Fatal(err)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2451 次 |
| 最近记录: |