common/json: add Unmarshal with method with syntax errors

This commit is contained in:
Mitchell Hashimoto 2013-08-09 16:50:24 -07:00
parent 51cfc355c9
commit 5166f511d2
4 changed files with 45 additions and 28 deletions

View File

@ -1,9 +1,9 @@
package command
import (
"encoding/json"
"errors"
"fmt"
jsonutil "github.com/mitchellh/packer/common/json"
"github.com/mitchellh/packer/packer"
"io/ioutil"
"log"
@ -116,7 +116,7 @@ func readFileVars(path string) (map[string]string, error) {
}
vars := make(map[string]string)
err = json.Unmarshal(bytes, &vars)
err = jsonutil.Unmarshal(bytes, &vars)
if err != nil {
return nil, err
}

40
common/json/unmarshal.go Normal file
View File

@ -0,0 +1,40 @@
package json
import (
"bytes"
"encoding/json"
"fmt"
)
// Unmarshal is wrapper around json.Unmarshal that returns user-friendly
// errors when there are syntax errors.
func Unmarshal(data []byte, i interface{}) error {
err := json.Unmarshal(data, i)
if err != nil {
syntaxErr, ok := err.(*json.SyntaxError)
if !ok {
return err
}
// We have a syntax error. Extract out the line number and friends.
// https://groups.google.com/forum/#!topic/golang-nuts/fizimmXtVfc
newline := []byte{'\x0a'}
// Calculate the start/end position of the line where the error is
start := bytes.LastIndex(data[:syntaxErr.Offset], newline) + 1
end := len(data)
if idx := bytes.Index(data[start:], newline); idx >= 0 {
end = start + idx
}
// Count the line number we're on plus the offset in the line
line := bytes.Count(data[:start], newline) + 1
pos := int(syntaxErr.Offset) - start - 1
err = fmt.Errorf("Error in line %d, char %d: %s\n%s",
line, pos, syntaxErr, data[start:end])
return err
}
return nil
}

View File

@ -0,0 +1 @@
package json

View File

@ -1,10 +1,9 @@
package packer
import (
"bytes"
"encoding/json"
"fmt"
"github.com/mitchellh/mapstructure"
jsonutil "github.com/mitchellh/packer/common/json"
"io/ioutil"
"sort"
)
@ -68,31 +67,8 @@ type rawProvisionerConfig struct {
// way.
func ParseTemplate(data []byte) (t *Template, err error) {
var rawTplInterface interface{}
err = json.Unmarshal(data, &rawTplInterface)
err = jsonutil.Unmarshal(data, &rawTplInterface)
if err != nil {
syntaxErr, ok := err.(*json.SyntaxError)
if !ok {
return
}
// We have a syntax error. Extract out the line number and friends.
// https://groups.google.com/forum/#!topic/golang-nuts/fizimmXtVfc
newline := []byte{'\x0a'}
// Calculate the start/end position of the line where the error is
start := bytes.LastIndex(data[:syntaxErr.Offset], newline) + 1
end := len(data)
if idx := bytes.Index(data[start:], newline); idx >= 0 {
end = start + idx
}
// Count the line number we're on plus the offset in the line
line := bytes.Count(data[:start], newline) + 1
pos := int(syntaxErr.Offset) - start - 1
err = fmt.Errorf("Error in line %d, char %d: %s\n%s",
line, pos, syntaxErr, data[start:end])
return
}