YAML
YAML Ain’t Markup Language
https://yaml.org/
YAML 语言教程 - 阮一峰
http://www.ruanyifeng.com/blog/2016/07/yaml.html
yaml在线编辑/转json
http://www.bejson.com/validators/yaml_editor/
Jackson Dataformat YAML 序列化
内部也使用了 snakeyaml
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.16.0</version>
</dependency>
Jackson 序列化输出 yaml 示例:
YAMLFactory yamlFactory = new YAMLFactory();
yamlFactory.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES);
yamlFactory.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
ObjectMapper objectMapper = new ObjectMapper(yamlFactory);
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
log.info(objectMapper.writeValueAsString(object));
yamlFactory.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES); 字符串不带引号
yamlFactory.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER); 去掉开头的 —
SnakeYAML
https://bitbucket.org/snakeyaml/snakeyaml-engine/src/master/
DumperOptions 输出格式选项
FLOW 格式和 BLOCK 格式
DumperOptions.FlowStyle.FLOW
:流样式,列表的元素被放在一行内,使用逗号进行分隔。DumperOptions.FlowStyle.BLOCK
:块样式,每个元素占据一行,使用缩进进行分隔。
# 使用流样式
course: [ linux , golang , python ]
- 1, 2, 3
# 使用块样式
course:
- linux
- golang
- python
- 1
- 2
- 3
ScalarStyle 标量格式
{
"ids": [
"1.3",
"1.3.1",
"1.3.1.1"
]
}
转 yaml 后:
ids:
- '1.3'
- 1.3.1
- 1.3.1.1
有的带单引号,有的不带单引号,是因为是否对特殊字符使用引号是由库自行决定的,以确保生成的YAML是有效的。
例如,如果一个字符串中含有在YAML语法中有特殊含义的字符,如冒号、破折号等,SnakeYaml 会自动添加引号以确保字符串被正确解析。
ScalarStyle 可设置为 DOUBLE_QUOTED 表示使所有的字符串都被双引号包围
DumperOptions options = new DumperOptions();
options.setDefaultScalarStyle(DumperOptions.ScalarStyle.DOUBLE_QUOTED);
Yaml yaml = new Yaml(options);
设置 Representer Class Tag 删除开头的包名
在使用 SnakeYAML 的 dump() 方法将 Java 对象转换为 YAML 格式时,默认情况下会在输出结果中包含 Java 类的全限定名,即返回第一行的 !!com.package.MyClass
设置 Representer.addClassTag(MyClass.class, Tag.MAP) 可去掉这一行
DumperOptions dumperOptions = new DumperOptions();
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Representer representer = new Representer(dumperOptions);
representer.addClassTag(MyClass.class, Tag.MAP);
Yaml yaml = new Yaml(representer, dumperOptions);
return yaml.dump(object);
How to hide bean type in snakeyaml
https://stackoverflow.com/questions/19246027/how-to-hide-bean-type-in-snakeyaml
对象转yaml时自定义yaml字段名
userName 输出为 user_name
TypeDescription typeDescription = new TypeDescription(MyClass.class);
typeDescription.substituteProperty("user_name", String.class, "getUserName", "setUserName");
typeDescription.setExcludes("userName");
Yaml yaml = new Yaml(representer, dumperOptions);
yaml.addTypeDescription(typeDescription);
return yaml.dump(object);
How to serialize fields with custom names using snake yaml in Java
https://stackoverflow.com/questions/54351787/how-to-serialize-fields-with-custom-names-using-snake-yaml-in-java
不太好用,最后直接在输出时定义了一个 Map,手动写死输出的 key 字段名
Map<String, Object> yamlMap = Map.of(
"user_name", user.getUserName(),
"user_address", user.getAddress())
);
DumperOptions dumperOptions = new DumperOptions();
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(dumperOptions);
return yaml.dum(yamlMap)
SnakeYaml 锚点和引用(Anchor and Alias, *id001 &id001)
SnakeYaml dump 输出的 yaml 中有 &id001 锚点和 *id001 引用,不方便使用方解析。
- child
condition: &id001 []
- child
condition: *id001
原因:
有锚点和引用是因为 SnakeYaml 检测到了完全相同的对象,我这里是空 List。
场景1
因为使用了 Java9 开始添加的 List.of()
构造的空列表,内部是同一个 ImmutableCollections.EMPTY_LIST
空列表对象,改为 Lists.newArrayList()
每次新建一个就好了。
场景2
当 userList 为空时
userList.stream().collect(Collectors.toList()) 每次返回的是一个新的 空list 对象。
userList.stream().toList() 返回的都是相同的 空list 对象。
@Test
public void anchorAndRef() {
List<String> list = List.of("abc", "dddd", "dfsf");
Map<String, Object> map = Map.of(
"toList1", list.stream().filter(s -> s.length() > 10).toList(),
"toList2", list.stream().filter(s -> s.length() > 10).toList(),
"collectToList1", list.stream().filter(s -> s.length() > 10).collect(Collectors.toList()),
"collectToList2", list.stream().filter(s -> s.length() > 10).collect(Collectors.toList())
);
Yaml yaml = new Yaml();
log.info("\n{}", yaml.dumpAsMap(map));
}
结果:
toList2: &id001 []
toList1: *id001
collectToList2: []
collectToList1: []
YAML Anchors And Aliases And How To Disable Them
https://ttl255.com/yaml-anchors-and-aliases-and-how-to-disable-them/
Java SnakeYaml - prevent dumping reference names
https://stackoverflow.com/questions/18202548/java-snakeyaml-prevent-dumping-reference-names
YAML 语法
基本语法
单一文件第一行,使用连续三个连字号 - 表示开始
‘#’ 表示注释
大小写敏感
使用缩进表示层级关系
缩进不允许使用tab,只允许空格
缩进的空格数不重要,只要相同层级的元素左对齐即可
键值对之间需要加一个空格来隔开 比如: key: value
yaml中的3种数据类型
标量/纯量(scalar):单个的、不可再分的值
对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
字符串
yaml 中的字符串加不加引号效果都是一样的(相对的,JSON中字符串必须加双引号)
多行字符串
字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格。
str: 这是一段
多行
字符串
转成json是
{
"str": "这是一段 多行 字符串"
}
|
竖线保留换行符
this: |
Foo
Bar
对应 json
{
"this": "Foo\nBar\n"
}
|+
保留末尾换行
|-
删除末尾换行
s1: |
Foo
s2: |+
Foo
s3: |-
Foo
对应 json
{
"s1": "Foo\n",
"s2": "Foo\n\n\n",
"s3": "Foo"
}
>
大于号折叠换行
that: >
Foo
Bar
转为 json
{
"that": "Foo Bar\n"
}
对象
字典:也叫做对象,多个键值对的组合
字典由多个key与value构成,value可以是标量,也可以是字典或者列表
key和value之间用 :分隔, 并且 : 后面有一个空格,
所有k/v可以放在一行,或者每个 k/v 分别放在不同行
account: { name: wang, age: 30 }
# 或者
account:
name: wang
age: 18
数组
放在同一行:用中括号括起来,多个元素逗号隔开
course: [ linux , golang , python ]
每个元素放在不同行,且元素前均使用”-“打头,并且 - 后有一个空格
course:
- linux
- golang
- python
yaml示例
#我是对象。。。顺便说一下注释是#
animal: pets
#注意:1.冒号后必须有空格
#2.可以将键值对写成一个行内对象
#3.空格标识层级关系
hash: {name: Stave, foo: bar }
#我是数组
type:
- Cat
- Dog
- Goldfish
Dog:
- big dog
- small dog
#我是纯量、最基本不可分
#数值型
number: 11.11
#布尔类型
isBeautiful: true
#时间采用
time: 20:41:58
#日期
date: 2018-7-9
#字符串
str0: '我是字符串'
str1: "我是双引号,单引号和双引号没有区别,不会对特殊字符转义"
str2: 'It''s a test,单引号中如果有单引号的字符,需要转义'
str3: ~ #~是空的意思
str4: !!str true '两个!表示强制转换'
str5: 我也可以不用引号引起来,厉害不
str6: '但是有空格 或者 特殊字符* 我就必须放在引号中了'
str7: 字符串可以换行
像这样
每换一行都要有空格标记,换行符会被转义为空格
#否则就报错,只能被注释了!!!!惨兮兮
str8: |
我不是一般的竖线,我是可以保留换行符的竖线
str9: >
我是
可以折叠换行
的大于号
str10: |-
我不想要末尾的换行符
str11: |+
我又想要末尾的换行符了,后面跟了一串尾巴
str12:
<p style="color:red">Hello world<p>
转成 json
{
"animal": "pets",
"hash": {
"name": "Stave",
"foo": "bar"
},
"type": [
"Cat",
"Dog",
"Goldfish"
],
"Dog": [
"big dog",
"small dog"
],
"number": 11.11,
"isBeautiful": true,
"time": 74518,
"date": "2018-7-9",
"str0": "我是字符串",
"str1": "我是双引号,单引号和双引号没有区别,不会对特殊字符转义",
"str2": "It's a test,单引号中如果有单引号的字符,需要转义",
"str3": null,
"str4": "true '两个!表示强制转换'",
"str5": "我也可以不用引号引起来,厉害不",
"str6": "但是有空格 或者 特殊字符* 我就必须放在引号中了",
"str7": "字符串可以换行 像这样 每换一行都要有空格标记,换行符会被转义为空格",
"str8": "我不是一般的竖线,我是可以保留换行符的竖线\n",
"str9": "我是 可以折叠换行 的大于号\n",
"str10": "我不想要末尾的换行符",
"str11": "我又想要末尾的换行符了,后面跟了一串尾巴\n",
"str12": "<p style=\"color:red\">Hello world<p>"
}
上一篇 2021年运动记录
下一篇 护肤
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: