github.com/rothwerx/packer@v0.9.0/common/json/unmarshal.go (about)

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  )
     8  
     9  // Unmarshal is wrapper around json.Unmarshal that returns user-friendly
    10  // errors when there are syntax errors.
    11  func Unmarshal(data []byte, i interface{}) error {
    12  	err := json.Unmarshal(data, i)
    13  	if err != nil {
    14  		syntaxErr, ok := err.(*json.SyntaxError)
    15  		if !ok {
    16  			return err
    17  		}
    18  
    19  		// We have a syntax error. Extract out the line number and friends.
    20  		// https://groups.google.com/forum/#!topic/golang-nuts/fizimmXtVfc
    21  		newline := []byte{'\x0a'}
    22  
    23  		// Calculate the start/end position of the line where the error is
    24  		start := bytes.LastIndex(data[:syntaxErr.Offset], newline) + 1
    25  		end := len(data)
    26  		if idx := bytes.Index(data[start:], newline); idx >= 0 {
    27  			end = start + idx
    28  		}
    29  
    30  		// Count the line number we're on plus the offset in the line
    31  		line := bytes.Count(data[:start], newline) + 1
    32  		pos := int(syntaxErr.Offset) - start - 1
    33  
    34  		err = fmt.Errorf("Error in line %d, char %d: %s\n%s",
    35  			line, pos, syntaxErr, data[start:end])
    36  		return err
    37  	}
    38  
    39  	return nil
    40  }