In [1]:
import ruamel.yaml
from __future__ import print_function

对象

对象的一组键值对,使用冒号结构表示。 CommentedMap相当于dict,是对dict的封装,加入了顺序性

In [2]:
inp = """\
# example
name:
  # details
  family: Smith   # very common
  given: Alice    # one of the siblings
"""
code = ruamel.yaml.load(inp, ruamel.yaml.RoundTripLoader)
In [3]:
print(ruamel.yaml.dump(code, Dumper=ruamel.yaml.RoundTripDumper), end='')
# example
name:
  # details
  family: Smith   # very common
  given: Alice    # one of the siblings
In [4]:
code['name']
Out[4]:
CommentedMap([('family', 'Smith'), ('given', 'Alice')])
In [5]:
code['name']['given']
Out[5]:
'Alice'

CommentedMap还支持在某个位置插入键值对,并且可以添加comment:

In [6]:
yaml_str = """\
first_name: Art
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""

data = ruamel.yaml.round_trip_load(yaml_str)
data.insert(1, 'last name', 'Vandelay', comment="new key")
print(ruamel.yaml.round_trip_dump(data))
first_name: Art
last name: Vandelay    # new key
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...

In [7]:
data
Out[7]:
CommentedMap([('first_name', 'Art'),
              ('last name', 'Vandelay'),
              ('occupation', 'Architect'),
              ('about',
               'Art Vandelay is a fictional character that George invents...')])

数组

一组连词线开头的行,构成一个数组。

In [8]:
inp1="""\
- Cat
- Dog
- Goldfish
"""
ani1 = ruamel.yaml.load(inp1, ruamel.yaml.RoundTripLoader)
ani1
Out[8]:
['Cat', 'Dog', 'Goldfish']

数据结构的子成员是一个数组,则可以在该项下面缩进一个空格

In [9]:
inp2="""\
-
 - Cat
 - Dog
 - Goldfish
"""
ani2 = ruamel.yaml.load(inp2, ruamel.yaml.RoundTripLoader)
ani2
Out[9]:
[['Cat', 'Dog', 'Goldfish']]

复合结构

对象和数组可以结合使用,形成复合结构。

In [10]:
com="""\
languages:
 - Ruby
 - Perl
 - Python 
websites:
 YAML: yaml.org 
 Ruby: ruby-lang.org 
 Python: python.org 
 Perl: use.perl.org
"""
comp=ruamel.yaml.load(com, ruamel.yaml.RoundTripLoader)
comp
Out[10]:
CommentedMap([('languages', ['Ruby', 'Perl', 'Python']),
              ('websites',
               CommentedMap([('YAML', 'yaml.org'),
                             ('Ruby', 'ruby-lang.org'),
                             ('Python', 'python.org'),
                             ('Perl', 'use.perl.org')]))])

纯量

纯量是最基本的、不可再分的值。以下数据类型都属于 JavaScript 的纯量。

  • 字符串
  • 布尔值
  • 整数
  • 浮点数
  • Null
  • 时间
  • 日期 数字用字面表示,布尔值为false和true,None/表示为~或者null,时间采用 ISO8601 格式,日期采用复合 iso8601 格式的年、月、日表示。。下面是一些简单例子
In [11]:
ruamel.yaml.load('false', ruamel.yaml.RoundTripLoader)
Out[11]:
False
In [12]:
ruamel.yaml.load('空: ~', ruamel.yaml.RoundTripLoader)
Out[12]:
CommentedMap([('空', None)])
In [13]:
ruamel.yaml.load('空: null', ruamel.yaml.RoundTripLoader)
Out[13]:
CommentedMap([('空', None)])
In [14]:
ruamel.yaml.load(' ISO8601 time: 2001-12-14t21:59:43.10-05:00 ', ruamel.yaml.RoundTripLoader)
Out[14]:
CommentedMap([('ISO8601 time',
               datetime.datetime(2001, 12, 15, 2, 59, 43, 100000))])
In [15]:
ruamel.yaml.load(' ISO8601 date: 1991-01-01 ', ruamel.yaml.RoundTripLoader)
Out[15]:
CommentedMap([('ISO8601 date', datetime.date(1991, 1, 1))])

YAML 允许你对数据进行强制转换:

In [16]:
ruamel.yaml.load(' 整数转字符串: !!str 123 ', ruamel.yaml.RoundTripLoader)
Out[16]:
CommentedMap([('整数转字符串', '123')])
In [17]:
ruamel.yaml.load(' 布尔转字符串: !!str true ', ruamel.yaml.RoundTripLoader)
Out[17]:
CommentedMap([('布尔转字符串', 'true')])

字符串默认不使用引号表示,但如果字符串之中包含空格或特殊字符,需要放在引号之中,并且换行符会被转为空格。

In [18]:
ruamel.yaml.load(" 回车: '跳\n水'", ruamel.yaml.RoundTripLoader)
Out[18]:
CommentedMap([('回车', '跳 水')])

单引号和双引号都可以使用,单引号之中如果还有单引号,必须连续使用两个单引号转义。

In [19]:
yin='''\
单引号: 'labor''s day'
双引号:  "跳
水"
'''
ruamel.yaml.load(yin, ruamel.yaml.RoundTripLoader)
Out[19]:
CommentedMap([('单引号', "labor's day"), ('双引号', '跳 水')])

多行字符串可以使用|保留换行符,也可以使用>折叠换行。+表示保留文字块末尾的换行,-表示删除字符串末尾的换行,这是默认方式。

In [20]:
duo='''\
this: |
  Foo
  Bar
that: >
  Foo
  Bar
'''
duo1='''\
s0: 
  Foo
  
s1: |
  Foo

s2: |+
  Foo


s3: |-
  Foo
'''
print(ruamel.yaml.load(duo, ruamel.yaml.RoundTripLoader))
print(ruamel.yaml.load(duo1, ruamel.yaml.RoundTripLoader))
CommentedMap([('this', 'Foo\nBar\n'), ('that', 'Foo Bar\n')])
CommentedMap([('s0', 'Foo'), ('s1', 'Foo\n'), ('s2', 'Foo\n\n\n'), ('s3', 'Foo')])

引用

锚点&和别名,可以用来引用,类似c++语法。 &用来建立锚点(defaults),<<表示合并到当前数据,用来引用锚点。

In [21]:
mao='''\
- &CENTER {x: 1, y: 2}
- &LEFT 
  x: 0
  y: 2
- &BIG {r: 10}
- &SMALL {r: 1}
# All the following maps are equal:
# Explicit keys
- x: 1
  y: 2
  r: 10
  label: center/big
# Merge one map
- <<: *CENTER
  r: 10
  label: center/big
# Merge multiple maps
- <<: [*CENTER, *BIG]
  label: center/big
# Override
- <<: [*BIG, *LEFT, *SMALL]
  x: 1
  label: center/big
'''
ruamel.yaml.load(mao, ruamel.yaml.RoundTripLoader)
Out[21]:
[CommentedMap([('x', 1), ('y', 2)]),
 CommentedMap([('x', 0), ('y', 2)]),
 CommentedMap([('r', 10)]),
 CommentedMap([('r', 1)]),
 CommentedMap([('x', 1), ('y', 2), ('r', 10), ('label', 'center/big')]),
 CommentedMap([('r', 10), ('label', 'center/big')]),
 CommentedMap([('label', 'center/big')]),
 CommentedMap([('x', 1), ('label', 'center/big')])]

因为json是yaml语法的子集,所以也可以用接送描述。如上

- &LEFT x: 0 y: 2

等价于

- &LEFT {x:0,y:2}