github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/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  }