1
2
3
4
5
6
7 package json
8
9 import (
10 "fmt"
11 "reflect"
12 "strconv"
13 "strings"
14
15 "encoding/json/internal"
16 "encoding/json/jsontext"
17 jsonv2 "encoding/json/v2"
18 )
19
20
21 func init() {
22 internal.TransformMarshalError = transformMarshalError
23 internal.TransformUnmarshalError = transformUnmarshalError
24 internal.NewMarshalerError = func(val any, err error, funcName string) error {
25 return &MarshalerError{reflect.TypeOf(val), err, funcName}
26 }
27
28 internal.NewRawNumber = func() any { return new(Number) }
29 internal.RawNumberOf = func(b []byte) any { return Number(b) }
30 }
31
32 func transformMarshalError(root any, err error) error {
33
34
35
36
37
38
39 if err, ok := err.(*jsonv2.SemanticError); err != nil {
40 if err.Err == nil {
41
42
43 return &UnsupportedTypeError{Type: err.GoType}
44 } else {
45
46
47
48
49 errStr := err.Err.Error()
50 if err.Err == internal.ErrCycle && err.GoType != nil {
51 errStr += " via " + err.GoType.String()
52 }
53 errStr = strings.TrimPrefix(errStr, "unsupported value: ")
54 return &UnsupportedValueError{Str: errStr}
55 }
56 } else if ok {
57 return (*UnsupportedValueError)(nil)
58 }
59 if err, _ := err.(*MarshalerError); err != nil {
60 err.Err = transformSyntacticError(err.Err)
61 return err
62 }
63 return transformSyntacticError(err)
64 }
65
66 func transformUnmarshalError(root any, err error) error {
67
68
69 if err, ok := err.(*jsonv2.SemanticError); err != nil {
70 if err.Err == internal.ErrNonNilReference {
71 return &InvalidUnmarshalError{err.GoType}
72 }
73 if err.Err == jsonv2.ErrUnknownName {
74 return fmt.Errorf("json: unknown field %q", err.JSONPointer.LastToken())
75 }
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 var value string
98 switch err.JSONKind {
99 case 'n', '"', '0':
100 value = err.JSONKind.String()
101 case 'f', 't':
102 value = "bool"
103 case '[', ']':
104 value = "array"
105 case '{', '}':
106 value = "object"
107 }
108 if len(err.JSONValue) > 0 {
109 isStrconvError := err.Err == strconv.ErrRange || err.Err == strconv.ErrSyntax
110 isNumericKind := func(t reflect.Type) bool {
111 if t == nil {
112 return false
113 }
114 switch t.Kind() {
115 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
116 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
117 reflect.Float32, reflect.Float64:
118 return true
119 }
120 return false
121 }
122 if isStrconvError && isNumericKind(err.GoType) {
123 value = "number"
124 if err.JSONKind == '"' {
125 err.JSONValue, _ = jsontext.AppendUnquote(nil, err.JSONValue)
126 }
127 err.Err = nil
128 }
129 value += " " + string(err.JSONValue)
130 }
131 var rootName string
132 if t := reflect.TypeOf(root); t != nil && err.JSONPointer != "" {
133 if t.Kind() == reflect.Pointer {
134 t = t.Elem()
135 }
136 rootName = t.Name()
137 }
138 fieldPath := string(err.JSONPointer)
139 fieldPath = strings.TrimPrefix(fieldPath, "/")
140 fieldPath = strings.ReplaceAll(fieldPath, "/", ".")
141 return &UnmarshalTypeError{
142 Value: value,
143 Type: err.GoType,
144 Offset: err.ByteOffset,
145 Struct: rootName,
146 Field: fieldPath,
147 Err: transformSyntacticError(err.Err),
148 }
149 } else if ok {
150 return (*UnmarshalTypeError)(nil)
151 }
152 return transformSyntacticError(err)
153 }
154
View as plain text