最近在学 Storm 的时候发现 Storm 的配置文件是 yaml 格式的,就好奇地查了下这个没听说过的格式(YAML - Wikipedia),这才发现原来不是什么新新物种,而是 2001 年就推出来了的文件格式。虽然 Yaml 相对于 XML 这种老大哥还差远了,但是后辈小子胜在年轻,有干劲,语法简单,功能强大,而且这几年相关工具的解析速度也提升了不少,大有超越 XML 这种大块头的趋势。简单地试用了下,发现压马路(“yaml”的拼音打出来就是这个)的语法真的是既简洁又优雅,让人爱不释手。于是,就这么愉快地决定了,以后的项目中没有其他要求的情况下全部使用 yaml 来做格式化,让 XML 先飞一会儿……
言归正传,Google 了一下,评价最好的解析工具还是 snakeyaml:
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.15</version>
</dependency>
对于下面这样基本的配置文件:
redis.host: rhost
redis.port: 6379
parse.rule:
- light
- weighted
使用 snakeyaml 解析 yaml 配置文件非常简单:
1 2 3 4 5 6 7 8 9 10 | public static Map<String, Object> loadMap(String file) throws IOException {
Yaml yaml = new Yaml();
Map<String, Object> map = null;
InputStream is = YamlUtil.class.getResourceAsStream(file);
if (is != null) {
map = (Map<String, Object>) yaml.load(is);
is.close();
}
return map;
}
|
对于下面这样比较复杂的对象 dump 文件:
!!me.weyo.yaml.Dev {
enabled: false,
inn: {name: III, timeout: 600000000},
port: 33333,
type: T1
}
--- !!me.weyo.yaml.Dev {
enabled: true,
inn: {name: UH, timeout: 180003300},
port: 10028,
type: T2
}
也可以很轻松的解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static List<Object> loadObjects(String file) throws IOException {
Yaml yaml = new Yaml();
List<Object> list = null;
InputStream is = YamlUtil.class.getResourceAsStream(file);
if (is != null) {
list = new ArrayList<Object>();
for (Object obj : yaml.loadAll(is)) {
list.add(obj);
}
is.close();
}
return list;
}
|
当然,如果有需要,还可以将对象 dump 到文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Yaml yaml = new Yaml();
RedisConnection redis = new RedisConnection();
redis.setHost("rh134");
redis.setPort(10029);
FileWriter output = null;
try {
output = new FileWriter("src/main/resources/topology.yaml");
} catch (IOException e) {
e.printStackTrace();
}
if (output != null)
yaml.dump(redis, output);
output.close();
|
综上所述,无所不能的 Yaml 真是居家旅行之必备 :)
Q & A
无法创建 Java 对象
Exception in thread "main" Can't construct a java object for tag:yaml.org,2002:me.weyo.yaml.Dev; exception=java.lang.NoSuchMethodException: me.weyo.yaml.Dev.<init>()
in 'reader', line 1, column 1:
!!me.weyo.yaml.Dev ...
^
这个错误表明被解析的对象(Dev)中没有默认的构造器(即只有带参数的构造器,没有无参构造器,snakeyaml 无法将对象解析为 Bean)。
解析错误异常
Exception in thread "main" while parsing a flow mapping
in 'reader', line 1, column 40:
... me.weyo.yaml.Dev {
^
expected ',' or '}', but got Value
in 'reader', line 3, column 7:
port: 33333
^
这是被解析的文件中有属性没有以逗号结束的缘故,例如,下面这样的文件描述就少了逗号:
# 错误的配置方式!
!!me.weyo.yaml.Dev {
enabled: false # 缺少逗号
inn: {name: III, timeout: 600000000}
port: 33333
type: T1
}
标记识别异常
Exception in thread "main" expected '<document start>', but found Tag
in 'reader', line 6, column 1:
!!me.weyo.yaml.Dev ...
^
这是由于缺少不同对象之间的分隔标识,例如这样的定义:
# 错误的配置方式!
!!me.weyo.yaml.Dev {
enabled: false,
inn: {name: III, timeout: 600000000},
port: 33333,
type: T1
}
!!me.weyo.yaml.Dev { # 缺少分隔符
enabled: true,
inn: {name: UH, timeout: 180003300},
port: 10028,
type: T2
}
Comments
comments powered by Disqus