github.com/ashishbhate/mattermost-server@v5.11.1+incompatible/utils/jsonutils/json.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package jsonutils 5 6 import ( 7 "bytes" 8 "encoding/json" 9 10 "github.com/pkg/errors" 11 ) 12 13 type HumanizedJsonError struct { 14 Err error 15 Line int 16 Character int 17 } 18 19 func (e *HumanizedJsonError) Error() string { 20 return e.Err.Error() 21 } 22 23 // HumanizeJsonError extracts error offsets and annotates the error with useful context 24 func HumanizeJsonError(err error, data []byte) error { 25 if syntaxError, ok := err.(*json.SyntaxError); ok { 26 return NewHumanizedJsonError(syntaxError, data, syntaxError.Offset) 27 } else if unmarshalError, ok := err.(*json.UnmarshalTypeError); ok { 28 return NewHumanizedJsonError(unmarshalError, data, unmarshalError.Offset) 29 } else { 30 return err 31 } 32 } 33 34 func NewHumanizedJsonError(err error, data []byte, offset int64) *HumanizedJsonError { 35 if err == nil { 36 return nil 37 } 38 39 if offset < 0 || offset > int64(len(data)) { 40 return &HumanizedJsonError{ 41 Err: errors.Wrapf(err, "invalid offset %d", offset), 42 } 43 } 44 45 lineSep := []byte{'\n'} 46 47 line := bytes.Count(data[:offset], lineSep) + 1 48 lastLineOffset := bytes.LastIndex(data[:offset], lineSep) 49 character := int(offset) - (lastLineOffset + 1) + 1 50 51 return &HumanizedJsonError{ 52 Line: line, 53 Character: character, 54 Err: errors.Wrapf(err, "parsing error at line %d, character %d", line, character), 55 } 56 }