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  }