| | |
| | |
| | |
| |
|
| | |
| |
|
| | package json |
| |
|
| | import ( |
| | "fmt" |
| | "reflect" |
| | "strconv" |
| | "strings" |
| |
|
| | "encoding/json/internal" |
| | "encoding/json/jsontext" |
| | jsonv2 "encoding/json/v2" |
| | ) |
| |
|
| | |
| | func init() { |
| | internal.TransformMarshalError = transformMarshalError |
| | internal.TransformUnmarshalError = transformUnmarshalError |
| | internal.NewMarshalerError = func(val any, err error, funcName string) error { |
| | return &MarshalerError{reflect.TypeOf(val), err, funcName} |
| | } |
| |
|
| | internal.NewRawNumber = func() any { return new(Number) } |
| | internal.RawNumberOf = func(b []byte) any { return Number(b) } |
| | } |
| |
|
| | func transformMarshalError(root any, err error) error { |
| | |
| | |
| | |
| | |
| | |
| | |
| | if err, ok := err.(*jsonv2.SemanticError); err != nil { |
| | if err.Err == nil { |
| | |
| | |
| | return &UnsupportedTypeError{Type: err.GoType} |
| | } else { |
| | |
| | |
| | |
| | |
| | errStr := err.Err.Error() |
| | if err.Err == internal.ErrCycle && err.GoType != nil { |
| | errStr += " via " + err.GoType.String() |
| | } |
| | errStr = strings.TrimPrefix(errStr, "unsupported value: ") |
| | return &UnsupportedValueError{Str: errStr} |
| | } |
| | } else if ok { |
| | return (*UnsupportedValueError)(nil) |
| | } |
| | if err, _ := err.(*MarshalerError); err != nil { |
| | err.Err = transformSyntacticError(err.Err) |
| | return err |
| | } |
| | return transformSyntacticError(err) |
| | } |
| |
|
| | func transformUnmarshalError(root any, err error) error { |
| | |
| | |
| | if err, ok := err.(*jsonv2.SemanticError); err != nil { |
| | if err.Err == internal.ErrNonNilReference { |
| | return &InvalidUnmarshalError{err.GoType} |
| | } |
| | if err.Err == jsonv2.ErrUnknownName { |
| | return fmt.Errorf("json: unknown field %q", err.JSONPointer.LastToken()) |
| | } |
| | if err.Err == internal.ErrNilInterface { |
| | err.Err = nil |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | var value string |
| | switch err.JSONKind { |
| | case 'n', '"', '0': |
| | value = err.JSONKind.String() |
| | case 'f', 't': |
| | value = "bool" |
| | case '[', ']': |
| | value = "array" |
| | case '{', '}': |
| | value = "object" |
| | } |
| | if len(err.JSONValue) > 0 { |
| | isStrconvError := err.Err == strconv.ErrRange || err.Err == strconv.ErrSyntax |
| | isNumericKind := func(t reflect.Type) bool { |
| | if t == nil { |
| | return false |
| | } |
| | switch t.Kind() { |
| | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, |
| | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, |
| | reflect.Float32, reflect.Float64: |
| | return true |
| | } |
| | return false |
| | } |
| | if isStrconvError && isNumericKind(err.GoType) { |
| | value = "number" |
| | if err.JSONKind == '"' { |
| | err.JSONValue, _ = jsontext.AppendUnquote(nil, err.JSONValue) |
| | } |
| | err.Err = nil |
| | } |
| | value += " " + string(err.JSONValue) |
| | } |
| | var rootName string |
| | if t := reflect.TypeOf(root); t != nil && err.JSONPointer != "" { |
| | if t.Kind() == reflect.Pointer { |
| | t = t.Elem() |
| | } |
| | rootName = t.Name() |
| | } |
| | fieldPath := string(err.JSONPointer) |
| | fieldPath = strings.TrimPrefix(fieldPath, "/") |
| | fieldPath = strings.ReplaceAll(fieldPath, "/", ".") |
| | return &UnmarshalTypeError{ |
| | Value: value, |
| | Type: err.GoType, |
| | Offset: err.ByteOffset, |
| | Struct: rootName, |
| | Field: fieldPath, |
| | Err: transformSyntacticError(err.Err), |
| | } |
| | } else if ok { |
| | return (*UnmarshalTypeError)(nil) |
| | } |
| | return transformSyntacticError(err) |
| | } |
| |
|