Skip to content

Commit

Permalink
common/json: add Unmarshal with method with syntax errors
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Aug 9, 2013
1 parent 51cfc35 commit 5166f51
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 28 deletions.
4 changes: 2 additions & 2 deletions common/command/template.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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
}
Expand Down
40 changes: 40 additions & 0 deletions common/json/unmarshal.go
Original file line number Diff line number Diff line change
@@ -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
}
1 change: 1 addition & 0 deletions common/json/unmarshal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package json
28 changes: 2 additions & 26 deletions packer/template.go
Original file line number Diff line number Diff line change
@@ -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"
)
Expand Down Expand Up @@ -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
}

Expand Down

0 comments on commit 5166f51

Please sign in to comment.