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 }