In code below should accept a multiline as string input as either JSON or YAML. It firsts attempts to read the input as JSON, and if JSON failed it makes a second attempt to read it as YAML if both failed return error.
Now the problem is with yaml.Unmarshal(). I check, it never returns an error if the input is JSON string. (correct or incorrect). The main issue yaml.Unmarshal never returns an error.
Initially, I thought it error on yaml.Unmarshal implementation, but it looks to me it makes the best effort when parsing input, and structure doesn't violate yaml; it never returns an error.
func SpecsFromString(str string) (*Something, error) {
r := strings.NewReader(str)
return ReadTenantsSpec(r)
}
func ReadSpec(b io.Reader) (*Spec, error) {
var spec Spec
buffer, err := ioutil.ReadAll(b)
if err != nil {
return nil, err
}
err = json.Unmarshal(buffer, &spec)
if err == nil {
return &spec, nil
}
err = yaml.Unmarshal(buffer, &spec)
if err == nil {
return &spec, nil
}
return nil, &InvalidTenantsSpec{"unknown format"}
}
So my question how to properly do this test if the input is JSON or YAML? It looks to me that the only way to do that on JSON unmashler differentiates two error cases. The reason is JSON generally more strict in structure. When the input is not JSON at all, and when input is JSON but an error in the structure of JSON. That second case will allow me never to call the yaml parser in the first place.
Maybe someone comes up with a more neat solution?
Thank you.