使用YAML Parser处理JSON;抛出制表符空格

时间:2016-10-16 16:18:44

标签: json parsing yaml

我有点不确定指尖的确切位置(当然不是我自己)

  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 “缩进字符不得用于缩进”

  4. 所以使用我的YAML解析器处理下面的JSON

    {
    \t"result" : "success",
    }
    

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

    遇到错误'不允许使用制表符进行缩进'< - 这似乎是正确的。

    但是那么“每个JSON文件也是一个有效的YAML文件”规则如何保持;因为我的文件是有效的JSON?

    由于标签字符没有意义,我应该运行预处理步骤来去除所有标签吗?由于字符串中允许的唯一空格是“空格” - 因此删除文件中的所有选项卡应该是安全的。

3 个答案:

答案 0 :(得分:2)

  

遇到错误'不允许使用标签进行缩进' < - 这似乎是正确的。

不是。

这是规范中的relevant production

[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) here(因为我们不在block-keyflow-key内。跳过一些步骤,我们到达s-separate-in-line,它允许制表符。

底线是JSON中的这个制表符不是缩进。缩进仅与块样式相关(即,分别不对序列和映射使用[{)。在Flow风格中,空格仅用于分离。

编辑:删除了示例链接,因为它有点误导。

编辑2 :回答第二个问题:不,不要删除标签。他们可能满足于标量!请参阅this example,其中表格实际上确定了块标量的缩进。

答案 1 :(得分:1)

JSON兼容性仅在YAML规范的1.2版中添加。在最初为YAML 1.1设计的解析器之上实现这种兼容性并非易事。

制表符在空格中没有固定的表示形式,编辑时取决于编辑器的设置(或默认值)。在实践中,这意味着您不应该在块样式模式下使用制表符,并且大多数解析器也不允许它们以流式模式使用。 “修复”这对1.2解析器的兼容性似乎并不是一个优先事项(至少它不适合我)。

所以这应该被你的解析器接受,但如果没有,你应该过滤掉它,但只能在行的开头。或者如果JSON自动生成,则调整生成器以使用空间。

答案 2 :(得分:0)

对于它的价值,我们总是使用TAB进行缩进 - 恕我直言,这是唯一合理的选择。因此,使用YAML是一个真正的问题。不想修改现有的YAML解析器(不好做的事),我编写了以下JavaScript函数来“解压缩”字符串,其结果可以提供给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行。没有经过高度测试,但非常简单明了 - 使用风险自负。