yaml解析示例(javascript)

图片发自简书App

yaml概述

yaml容易被机器解析,且人类可读。

这是一个谎言吧!

利用冒号分隔键和值,用中划线表示数组。这就是所有的规则。

年轻人都喜欢simple,这是句名言。可以去官网查看详情,和其他解析库。

yaml示例

yaml:data 
seq: 
- 
  1:yi 
  2:er 
- 
  1:one
  2 :two

js的全部代码


/**
 * yaml 解析简单实现
 */
var pos = 0;
/**
 * token
 * @returns
 */
function getNextToken() {
    if (pos == len) {
        return {
            type : "EOF"
        }
    }
    skipSpace();
    var c = yaml[pos];
    if (isString(c)) {
        return getString();
    }

    pos++;
    return {
        val : c,
        type : c
    };
}
/**
 * next but do not changed
 * @param n
 * @returns
 */
function peek(n) {
    skipSpace();
    return yaml[pos]
}
function skipSpace() {
    var c = yaml[pos];
    while (isSpace(c) && pos < len) {
        pos++;
        c = yaml[pos];
    }

}
function isSpace(c) {
    return c == ' ' || c == '\t' || c == '\n'

}
function getString() {
    var c = yaml[pos];
    var str = "";
        //没有考虑转义字符
    while (isString(c) && pos < len) {
        str += yaml[pos];
        pos++;
        c = yaml[pos];
    }

    return {
        val : str,
        type : "str"
    };
}
function isString(c) {
    return !isSpace(c) && !isSpecial(c);
}
function isSpecial(c) {
    return c == ':' || c == '-'
}


//can be simple type kv array
function getYaml() {
    var currentToken = getNextToken();

    while (currentToken.type != "EOF") {

        if (peek() == ':') {
            return getkv(currentToken)
        }
        if (currentToken.type == '-') {
            return getArray();
        }
                //string
        return currentToken.val;
    }

}
//键值对  其后不能是序列符号 
function getkv(currentToken) {
    var yaml = {};

    getNextToken();
    yaml[currentToken.val] = getYaml();
    while (peek() != "-"&&currentToken.type != "EOF") {
        
        currentToken = getNextToken();

        getNextToken();//check : or thorw error
        yaml[currentToken.val] = getYaml();

    }

    return yaml;
}
function getArray() {
    var a = [];
    a.push(getYaml());
    while (peek() == "-") {
        getNextToken();//check -
        a.push(getYaml());
    }
    return a;
}

var yaml = "yaml:data " + "seq: " + "- 1:yi 2:er " + " - 1:one 2 :two";

var len = yaml.length;
console.log(JSON.stringify(getYaml()))
//{"yaml":"data","seq":[{"1":"yi","2":"er"},{"1":"one","2":"two"}]}

没有错误处理,也没有很好的封装,但是有详细的注释,容易改写和理解。

json结果查看


{"yaml":"data",
 "seq":
      [  {"1":"yi",
           "2":"er"
         },
        {"1":"one",
         "2":"two"
        }
      ]
}

对比一下,我个人感觉对于yaml,机器确实容易解析,而可读性并不算太好,可写性很好。不知道为什么最近就火了。

尽量不写简单的示例了,可能方法不对,太无聊,得做点有意义的事情了[加了几个小时班,却没有工作成果]。不知道怎么从大体上把屋项目,现在只能看到代码里面的细节,几乎看不到思想层面的东西。

其实我前面的定义就是错误的,没有考虑空格分隔的情况,这里的空格是有语法意义的(两个空格的缩减),类似python的语法。

对于给出的示例正好可以运行。复杂的数据会把后面的对象加在前面的对象上,类似于if if else中的第二个else会被吞掉,其实好的做法是利用大括号({}),就是程序块中一句也加上括号。

欺骗大家了,解析的结果其实是错误的。
那么现在如何修改昵?首先设定两个空格的缩进,再根据缩进的结构进行读取。isSpace和peek需要改写。getYaml的时候语言增加参数记录当前的位置。说实话,我后来尝试改写代码,也没有正确解析,对我来说不好解析…。在网上看了一下,Python的解析,用了一下hack,才能正确。

当然这个时候其实和人眼处理这样的东西是一样的,需要记忆功能前面空格数量。在没有工具支持,当编辑和阅读很长的文件时,基本属于瞎猜,和读几十层的js闭包一样让人崩溃。

yaml的最后一个优点,就是可以用流的方式解析,就是yaml文件的大小几乎可以没有限制,利用buf在没有传递完全的时候也可以处理,对网络传递和文件读取特别有意义。这是因为没有开始符和终结符的原因,当然这些的文件要有一定的格式要求,就是缩进不能太深。把json或者xml的第一个开始符和最后的结束符去掉,我想我们也可以构造出这样的结构。据说Google map为了节省流量,用的就是自己设计的一种格式来传递数据,然后自己解析。当然任何人都可以根据业务来设计自己最合适的数据格式,但是普遍情况下这样的好处比缺点还多,还是使用通用的比较稳妥。

最近涌现出很多新东西,新技术的快速入门的东西并不能让人感到尽兴,又不容易找到好的阅读材料。
欢迎阅读我的其它文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,923评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,954评论 6 342
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,219评论 2 33
  • Ubuntu的发音 Ubuntu,源于非洲祖鲁人和科萨人的语言,发作 oo-boon-too 的音。了解发音是有意...
    萤火虫de梦阅读 99,566评论 9 467
  • 38#:明粹 亲爱的怡坤: 半年没见,好想你啊。 毕业那天你离开学校的时候,我还在沉睡,因为前一晚通宵嗨歌,没能亲...
    豆南国阅读 136评论 0 0