package main
import (
"encoding/json"
"fmt"
)
// 自定义错误类型
type JSONParseError struct {
ErrType string
Context string
Path string
}
func (e *JSONParseError) Error() string {
return fmt.Sprintf("%s: %s at path %s", e.ErrType, e.Context, e.Path)
}
// 自定义错误接口
type JSONError interface {
Error() string
GetErrType() string
GetContext() string
GetPath() string
}
func (e *JSONParseError) GetErrType() string {
return e.ErrType
}
func (e *JSONParseError) GetContext() string {
return e.Context
}
func (e *JSONParseError) GetPath() string {
return e.Path
}
// 自定义解析函数
func CustomUnmarshal(data []byte, v interface{}) error {
var pathStack []string
decoder := json.NewDecoder(&jsonReader{data: data})
decoder.UseNumber()
var err error
err = decoder.Decode(v)
if err != nil {
var parseErr *JSONParseError
if syntaxErr, ok := err.(*json.SyntaxError); ok {
parseErr = &JSONParseError{
ErrType: "SyntaxError",
Context: fmt.Sprintf("invalid character %q at position %d", syntaxErr.Error()[10], syntaxErr.Offset),
Path: buildPath(pathStack),
}
} else if unmarshalTypeErr, ok := err.(*json.UnmarshalTypeError); ok {
parseErr = &JSONParseError{
ErrType: "UnmarshalTypeError",
Context: fmt.Sprintf("found type %s, expected %s", unmarshalTypeErr.Value, unmarshalTypeErr.Type),
Path: buildPath(pathStack),
}
} else if unexpectedEndErr, ok := err.(*json.UnexpectedEndError); ok {
parseErr = &JSONParseError{
ErrType: "UnexpectedEOFError",
Context: fmt.Sprintf("unexpected end of JSON input at position %d", unexpectedEndErr.Offset),
Path: buildPath(pathStack),
}
} else {
parseErr = &JSONParseError{
ErrType: "UnknownError",
Context: err.Error(),
Path: buildPath(pathStack),
}
}
return parseErr
}
return nil
}
func buildPath(pathStack []string) string {
if len(pathStack) == 0 {
return ""
}
var path string
for _, p := range pathStack {
path += "/" + p
}
return path
}
type jsonReader struct {
data []byte
pos int
}
func (jr *jsonReader) Read(p []byte) (n int, err error) {
if jr.pos >= len(jr.data) {
return 0, nil
}
n = copy(p, jr.data[jr.pos:])
jr.pos += n
return n, nil
}
// 使用示例
func main() {
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
jsonData := []byte(`{"name":"John", "age":"twenty"}`)
var person Person
err := CustomUnmarshal(jsonData, &person)
if err != nil {
if jsonErr, ok := err.(JSONError); ok {
fmt.Printf("Error Type: %s\n", jsonErr.GetErrType())
fmt.Printf("Context: %s\n", jsonErr.GetContext())
fmt.Printf("Path: %s\n", jsonErr.GetPath())
} else {
fmt.Println("Unexpected error:", err)
}
} else {
fmt.Println("Successfully unmarshaled:", person)
}
}
- 自定义错误类型与接口:定义了
JSONParseError
结构体来存储错误类型、上下文和路径信息,并实现了JSONError
接口,包含获取这些信息的方法。
- 自定义解析函数:
CustomUnmarshal
函数使用json.NewDecoder
进行解码,并在发生错误时,根据错误类型构造自定义的JSONParseError
。
- 路径构建:
buildPath
函数用于构建JSON数据的路径。
- 使用示例:在
main
函数中,定义了一个简单的结构体Person
,并尝试解析包含类型不匹配的JSON数据,展示如何处理和输出自定义错误。