用YAML解析器处理JSON在制表符上抛出空白

avwztpqn  于 2023-05-08  发布在  其他
关注(0)|答案(3)|浏览(192)

我有点不确定到底该把矛头指向哪里(当然除了我自己)

  1. JSON是YAML 1.2 http://www.yaml.org/spec/1.2/spec.html的子集“每个JSON文件也是有效的YAML文件”
  2. JSON可以将制表符设置为“无关紧要的空白”-包括制表符http://www.ietf.org/rfc/rfc4627.txt“允许使用无关紧要的空白...”
  3. YAML不允许使用制表符进行缩进http://www.yaml.org/spec/1.2/spec.html“制表符字符不得用于缩进”
    所以使用我的YAML解析器来处理下面的JSON
{
\t"result" : "success",
}

注意:\t只是为了可视化,输入包含一个真实的的制表符。

点击一个错误'不允许使用制表符缩进' <-这似乎是正确的。
但是“每个JSON文件也是一个有效的YAML文件”规则是如何成立的;因为我的文件是有效的JSON?
由于制表符是没有意义的,我应该运行一个预处理步骤来剥离所有制表符吗?由于字符串中唯一允许的空格是'space'-因此只需去掉文件中的所有制表符就应该是安全的。

rqmkfv5c

rqmkfv5c1#

点击一个错误'不允许使用制表符缩进' <-这似乎是正确的。
它不是。
这是规范中的相关生产:

[140]   c-flow-mapping(n,c) ::= “{” s-separate(n,c)?
                                ns-s-flow-map-entries(n,in-flow(c))? “}”

s-separate(n,c)在这里解析为s-separate-lines(n)(因为我们不在block-keyflow-key内部)。跳过一些步骤,我们到达允许制表符的s-separate-in-line。
底线是JSON中的这个制表符不是缩进。压痕仅与块样式相关(即不分别对序列和Map使用[{)。在Flow样式中,空白仅用于分隔。

  • 编辑 *:删除示例链接,因为它有点误导。
  • 编辑2*:回答您的第二个问题:不,不要剥离标签。他们可能满足于标量!请参阅此示例,其中表格实际上确定了块标量的缩进。
yyyllmsg

yyyllmsg2#

JSON兼容性仅在YAML规范的1.2版本中添加。在最初为YAML 1.1设计的解析器上实现这种兼容性并不简单。
制表符在空格中没有固定的表示形式,何时编辑取决于编辑器的设置(或默认设置)。在实践中,这意味着在块样式模式中根本不应该使用制表符,而且大多数解析器也不允许在流样式模式中使用制表符。
所以你的解析器应该接受这个,就像ruamel.yaml>=0.17.24一样(当使用纯Python时),但是如果它不接受,你可以过滤掉它,但是只能在行的开头,如果你知道TAB不用于文字或流风格的标量。
如果JSON是自动生成的,请调整生成器以使用空格。

xxhby3vn

xxhby3vn3#

无论如何,我们总是使用TAB来进行缩进--恕我直言,这是唯一合理的选择。因此,使用YAML是一个真实的的问题。我不想修改现有的YAML解析器(这是一件坏事),我写了下面的JavaScript函数来“untabify”字符串,其结果可以提供给YAML解析器:

function untabify(str, indent='   ') {

return str.replace(/^(\t*)(\x20*)/gm, function(match, p1, p2) {

    // --- Keep track of line numbers, for error messages
    if (untabify.hasOwnProperty('lineNumber')) {
        ++untabify.lineNumber;
        }
    else {
        untabify.lineNumber = 0;
        }

    // --- It's an error for space characters to appear in indentation
    if (p2.length > 0) {
        throw "Space character not allowed in indentation on line "
                + untabify.lineNumber;
        }

    return indent.repeat(p1.length);
    });
} // untabify()

有了它,你可以简单地做到这一点(除了删除跟踪行号的代码,我不确定我如何改进它):

var str = `
---
- StudentName
- StudentCode
- Age
- DateOfBirth
- Gender
-
    - lCustomData
    - Name
    - Value
-
    - lRaces
    - bPrimaryRace
    - Race
    - RaceCode
-
    - lGoals
    - iGoal
    - Goal
    - BeginDate
    - EndDate
    -
        - lObjectives
        - iObjective
        - Objective
`;

var lStudentFields = YAML.parse(untabify(str));

如果你试图在缩进中混合使用TAB和空格,它会抛出一个错误。另外,请注意行号从0开始,但由于我通常的用法与示例中一样,反勾字符串从它开始的地方开始,第一个行号0将是从那里开始的空行,因此示例中的'---'实际上是行号1。没有经过高度测试,但相当简单和明确-使用风险自担。

相关问题