|
1 | 1 | package declcfg
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "bytes" |
4 | 5 | "encoding/json"
|
5 | 6 | "errors"
|
6 | 7 | "fmt"
|
@@ -135,7 +136,7 @@ func LoadReader(r io.Reader) (*DeclarativeConfig, error) {
|
135 | 136 |
|
136 | 137 | var in Meta
|
137 | 138 | if err := json.Unmarshal(doc, &in); err != nil {
|
138 |
| - return nil, err |
| 139 | + return nil, fmt.Errorf("unmarshal error: %s", resolveUnmarshalErr(doc, err)) |
139 | 140 | }
|
140 | 141 |
|
141 | 142 | switch in.Schema {
|
@@ -186,3 +187,47 @@ func LoadFile(root fs.FS, path string) (*DeclarativeConfig, error) {
|
186 | 187 |
|
187 | 188 | return cfg, nil
|
188 | 189 | }
|
| 190 | + |
| 191 | +func resolveUnmarshalErr(data []byte, err error) string { |
| 192 | + var te *json.UnmarshalTypeError |
| 193 | + if errors.As(err, &te) { |
| 194 | + return formatUnmarshallErrorString(data, te.Error(), te.Offset) |
| 195 | + } |
| 196 | + var se *json.SyntaxError |
| 197 | + if errors.As(err, &se) { |
| 198 | + return formatUnmarshallErrorString(data, se.Error(), se.Offset) |
| 199 | + } |
| 200 | + return err.Error() |
| 201 | +} |
| 202 | + |
| 203 | +func formatUnmarshallErrorString(data []byte, errmsg string, offset int64) string { |
| 204 | + sb := new(strings.Builder) |
| 205 | + _, _ = sb.WriteString(fmt.Sprintf("%s at offset %d (indicated by <==)\n ", errmsg, offset)) |
| 206 | + // attempt to present the erroneous JSON in indented, human-readable format |
| 207 | + // errors result in presenting the original, unformatted output |
| 208 | + var pretty bytes.Buffer |
| 209 | + err := json.Indent(&pretty, data, "", " ") |
| 210 | + if err == nil { |
| 211 | + pString := pretty.String() |
| 212 | + // calc the prettified string offset which correlates to the original string offset |
| 213 | + var pOffset, origOffset int64 |
| 214 | + origOffset = 0 |
| 215 | + for origOffset = 0; origOffset < offset; { |
| 216 | + pOffset++ |
| 217 | + if pString[pOffset] != '\n' && pString[pOffset] != ' ' { |
| 218 | + origOffset++ |
| 219 | + } |
| 220 | + } |
| 221 | + _, _ = sb.WriteString(pString[:pOffset]) |
| 222 | + _, _ = sb.WriteString(" <== ") |
| 223 | + _, _ = sb.WriteString(pString[pOffset:]) |
| 224 | + } else { |
| 225 | + for i := int64(0); i < offset; i++ { |
| 226 | + _ = sb.WriteByte(data[i]) |
| 227 | + } |
| 228 | + _, _ = sb.WriteString(" <== ") |
| 229 | + _, _ = sb.Write(data[offset:]) |
| 230 | + } |
| 231 | + |
| 232 | + return sb.String() |
| 233 | +} |
0 commit comments