diff --git a/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder.go b/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder.go index 27b7500eba9..6ebfaea707d 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder.go @@ -69,11 +69,10 @@ func (d *YAMLToJSONDecoder) Decode(into interface{}) error { } if len(bytes) != 0 { - data, err := yaml.YAMLToJSON(bytes) + err := yaml.Unmarshal(bytes, into) if err != nil { - return err + return YAMLSyntaxError{err} } - return json.Unmarshal(data, into) } return err } @@ -184,6 +183,23 @@ type YAMLOrJSONDecoder struct { rawData []byte } +type JSONSyntaxError struct { + Line int + Err error +} + +func (e JSONSyntaxError) Error() string { + return fmt.Sprintf("json: line %d: %s", e.Line, e.Err.Error()) +} + +type YAMLSyntaxError struct { + err error +} + +func (e YAMLSyntaxError) Error() string { + return e.err.Error() +} + // NewYAMLOrJSONDecoder returns a decoder that will process YAML documents // or JSON documents from the given reader as a stream. bufferSize determines // how far into the stream the decoder will look to figure out whether this @@ -226,7 +242,10 @@ func (d *YAMLOrJSONDecoder) Decode(into interface{}) error { start := strings.LastIndex(js[:syntax.Offset], "\n") + 1 line := strings.Count(js[:start], "\n") - return fmt.Errorf("json: line %d: %s", line, syntax.Error()) + return JSONSyntaxError{ + Line: line, + Err: fmt.Errorf(syntax.Error()), + } } } return err diff --git a/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder_test.go b/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder_test.go index 5712b30794a..54daec27432 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/yaml/decoder_test.go @@ -314,3 +314,36 @@ func testReadLines(t *testing.T, lineLengths []int) { } } } + +func TestTypedJSONOrYamlErrors(t *testing.T) { + s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`{ + "foo": { + "stuff": 1 + "otherStuff": 2 + } +} + `)), 100) + obj := generic{} + err := s.Decode(&obj) + if err == nil { + t.Fatal("expected error with json: prefix, got no error") + } + if _, ok := err.(JSONSyntaxError); !ok { + t.Fatalf("expected %q to be of type JSONSyntaxError", err.Error()) + } + + s = NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`--- +stuff: 1 + test-foo: 1 + +--- + `)), 100) + obj = generic{} + err = s.Decode(&obj) + if err == nil { + t.Fatal("expected error with yaml: prefix, got no error") + } + if _, ok := err.(YAMLSyntaxError); !ok { + t.Fatalf("expected %q to be of type YAMLSyntaxError", err.Error()) + } +}