DecodeJSON with byte offsets for parse failures

Go
package jsonx

import (
    "bytes"
    "encoding/json"
    "errors"
    "fmt"
    "io"
)

// DecodeJSON decodes one JSON value into out and adds context to failures:
// byte offsets for syntax and type errors, and a clear message for truncation.
func DecodeJSON(data []byte, out any) error {
    dec := json.NewDecoder(bytes.NewReader(data))
    if err := dec.Decode(out); err != nil {
        var syn *json.SyntaxError
        var typ *json.UnmarshalTypeError
        switch {
        case errors.As(err, &syn):
            return fmt.Errorf("invalid JSON at byte %d: %w", syn.Offset, err)
        case errors.As(err, &typ):
            return fmt.Errorf("field %q: expected %s at byte %d", typ.Field, typ.Type, typ.Offset)
        case errors.Is(err, io.ErrUnexpectedEOF), errors.Is(err, io.EOF):
            return fmt.Errorf("truncated JSON document: %w", err)
        default:
            return fmt.Errorf("decode JSON: %w", err)
        }
    }
    if dec.More() {
        return errors.New("unexpected trailing data after JSON value")
    }
    return nil
}