【发布时间】:2021-06-28 02:03:30
【问题描述】:
在下面的代码中,应该接受多行作为 JSON 或 YAML 格式的字符串输入。它首先尝试将输入读取为 JSON,如果 JSON 失败,它会再次尝试将其读取为 YAML,如果两者都失败则返回错误。
现在问题出在 yaml.Unmarshal() 上。我检查了一下,如果输入是 JSON 字符串,它永远不会返回错误。 (正确或不正确)。主要问题 yaml.Unmarshal 永远不会返回错误。
最初,我认为它在 yaml.Unmarshal 实现上出错,但在我看来,它在解析输入时尽了最大努力,并且结构不违反 yaml;它永远不会返回错误。
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"}
}
所以我的问题是,如果输入是 JSON 或 YAML,如何正确执行此测试? 在我看来,在 JSON unmashler 上做到这一点的唯一方法是区分 两个错误案例。原因是 JSON 通常在结构上更严格。 当输入根本不是 JSON,当输入是 JSON 但 JSON 的结构有错误时。第二种情况将允许我永远不会调用 yaml 解析器 首先。
也许有人想出了一个更巧妙的解决方案?
谢谢。
【问题讨论】:
-
正则表达式是否可以首先检测输入是否为 JSON? stackoverflow.com/a/3710506/13906951
-
并非如此。因为 parse 必须足够智能以报告两种不同的错误情况。我检查了 go JSON 只报告一个错误,格式不正确。想象一下,正则表达式检查通过,JSON 解析失败,我尝试调用 yaml 并且它永远不会失败......我认为唯一的方法是强制 yaml 规范中必须始终存在的值。
-
YAML is a superset of JSON。如果您可以选择,我会更改函数参数以要求指定输入格式,而不是编写与格式无关的实现。
-
@blackgreen 我同意我认为这是唯一的出路。在 yaml 中强制执行特定的强制值。
-
@JohnnyBonelli,我在答案中添加了一个基本示例。在我的示例中,我没有任何特定的评分标准,但我演示了包装阅读器并评估已处理输入的一部分。我使用换行符作为分隔符,但它实际上可以是任何你认为会给出准确框架的东西,直到任何源文件的全部内容。