Skip to content

Commit 5ca769e

Browse files
author
k8s-merge-robot
committed
Merge pull request kubernetes#25038 from mfojtik/json-line
Automatic merge from submit-queue Display line number on JSON errors Related issue: kubernetes#12231 This PR will introduce line numbers for all JSON errors in the CLI: (this is existing error reporting for YAML) ```console $ kubectl create -f broken.yaml yaml: line 8: mapping values are not allowed in this context ``` (this is error reporting proposed in this PR for JSON) ```console $ kubectl create -f broken.json json: line 35: invalid character '{' after object key ``` (and this is the current reporting:) ```console $ kubectl create -f broken.json invalid character '{' after object key ``` [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/.github/PULL_REQUEST_TEMPLATE.md?pixel)]()
2 parents c7343fc + 543a8b2 commit 5ca769e

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

pkg/util/yaml/decoder.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import (
2020
"bufio"
2121
"bytes"
2222
"encoding/json"
23+
"fmt"
2324
"io"
25+
"io/ioutil"
26+
"strings"
2427
"unicode"
2528

2629
"github.com/ghodss/yaml"
@@ -203,7 +206,20 @@ func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
203206
d.decoder = NewYAMLToJSONDecoder(buffer)
204207
}
205208
}
206-
return d.decoder.Decode(into)
209+
err := d.decoder.Decode(into)
210+
if jsonDecoder, ok := d.decoder.(*json.Decoder); ok {
211+
if syntax, ok := err.(*json.SyntaxError); ok {
212+
data, readErr := ioutil.ReadAll(jsonDecoder.Buffered())
213+
if readErr != nil {
214+
glog.V(4).Infof("reading stream failed: %v", readErr)
215+
}
216+
js := string(data)
217+
start := strings.LastIndex(js[:syntax.Offset], "\n") + 1
218+
line := strings.Count(js[:start], "\n")
219+
return fmt.Errorf("json: line %d: %s", line, syntax.Error())
220+
}
221+
}
222+
return err
207223
}
208224

209225
// GuessJSONStream scans the provided reader up to size, looking

pkg/util/yaml/decoder_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"encoding/json"
2323
"fmt"
2424
"io"
25+
"strings"
2526
"testing"
2627
)
2728

@@ -125,6 +126,41 @@ stuff: 1
125126
}
126127
}
127128

129+
func TestDecodeBrokenYAML(t *testing.T) {
130+
s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`---
131+
stuff: 1
132+
test-foo: 1
133+
134+
---
135+
`)), 100)
136+
obj := generic{}
137+
err := s.Decode(&obj)
138+
if err == nil {
139+
t.Fatal("expected error with yaml: prefix, got no error")
140+
}
141+
if !strings.HasPrefix(err.Error(), "yaml: line 2:") {
142+
t.Fatalf("expected %q to have 'yaml: line 2:' prefix", err.Error())
143+
}
144+
}
145+
146+
func TestDecodeBrokenJSON(t *testing.T) {
147+
s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`{
148+
"foo": {
149+
"stuff": 1
150+
"otherStuff": 2
151+
}
152+
}
153+
`)), 100)
154+
obj := generic{}
155+
err := s.Decode(&obj)
156+
if err == nil {
157+
t.Fatal("expected error with json: prefix, got no error")
158+
}
159+
if !strings.HasPrefix(err.Error(), "json: line 3:") {
160+
t.Fatalf("expected %q to have 'json: line 3:' prefix", err.Error())
161+
}
162+
}
163+
128164
type generic map[string]interface{}
129165

130166
func TestYAMLOrJSONDecoder(t *testing.T) {

0 commit comments

Comments
 (0)