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