流风格

2022.06.17

本文按照YAML官方文档1.2.2版本翻译总结而成

https://yaml.org/spec/1.2.2/#chapter-7-flow-style-productions

YAML’s flow styles can be thought of as the natural extension of JSON to cover folding long content lines for readability, tagging nodes to control construction of native data structures and using anchors and aliases to reuse constructed object instances.

7.1. Alias Nodes

Subsequent occurrences of a previously serialized node are presented as alias nodes. The first occurrence of the node must be marked by an anchor to allow subsequent occurrences to be presented as alias nodes.

An alias node is denoted by the “*” indicator. The alias refers to the most recent preceding node having the same anchor. It is an error for an alias node to use an anchor that does not previously occur in the document. It is not an error to specify an anchor that is not used by any alias node.

Note that an alias node must not specify any properties or content, as these were already specified at the first occurrence of the node.

Example 7.1 Alias Nodes

First occurrence: &anchor Foo Second occurrence: *anchor Override anchor: &anchor Bar Reuse anchor: *anchor{ "First occurrence": &A "Foo", "Override anchor": &B "Bar", "Second occurrence": *A, "Reuse anchor": *B }
  

Legend:

7.2. Empty Nodes

YAML allows the node content to be omitted in many cases. Nodes with empty content are interpreted as if they were plain scalars with an empty value. Such nodes are commonly resolved to a “null” value.

In the examples, empty scalars are sometimes displayed as the glyph “°” for clarity. Note that this glyph corresponds to a position in the characters stream rather than to an actual character.

Example 7.2 Empty Content

{ foo : !!str°, !!str° : bar, }{ "foo": "", "": "bar" }
  

Legend:

Both the node’s properties and node content are optional. This allows for a completely empty node. Completely empty nodes are only valid when following some explicit indication for their existence.

Example 7.3 Completely Empty Flow Nodes

{ ? foo :°, °: bar, }{ "foo": null, null : "bar" }
  

Legend:

7.3. Flow Scalar Styles

YAML provides three flow scalar styles: double-quoted, single-quoted and plain (unquoted). Each provides a different trade-off between readability and expressive power.

The scalar style is a presentation detail and must not be used to convey content information, with the exception that plain scalars are distinguished for the purpose of tag resolution.

7.3.1. Double-Quoted Style

The double-quoted style is specified by surrounding “"” indicators. This is the only style capable of expressing arbitrary strings, by using “\escape sequences. This comes at the cost of having to escape the “\” and “"” characters.

Double-quoted scalars are restricted to a single line when contained inside an implicit key.

Example 7.4 Double Quoted Implicit Keys

"implicit block key" : [ "implicit flow key" : value, ]{ "implicit block key": [ { "implicit flow key": "value" } ] }
  

Legend:

In a multi-line double-quoted scalar, line breaks are subject to flow line folding, which discards any trailing white space characters. It is also possible to escape the line break character. In this case, the escaped line break is excluded from the content and any trailing white space characters that precede the escaped line break are preserved. Combined with the ability to escape white space characters, this allows double-quoted lines to be broken at arbitrary positions.

Example 7.5 Double Quoted Line Breaks

"folded·↓ to a space,→↓ ·↓ to a line feed, or·→\↓ ·\·→non-content""folded to a space,\nto a line feed, or \t \tnon-content"
  

Legend:

All leading and trailing white space characters on each line are excluded from the content. Each continuation line must therefore contain at least one non-space character. Empty lines, if any, are consumed as part of the line folding.

Example 7.6 Double Quoted Lines

"·1st non-empty↓ ↓ ·2nd non-empty· →3rd non-empty·"" 1st non-empty\n2nd non-empty 3rd non-empty "
  

Legend:

7.3.2. Single-Quoted Style

The single-quoted style is specified by surrounding “'” indicators. Therefore, within a single-quoted scalar, such characters need to be repeated. This is the only form of escaping performed in single-quoted scalars. In particular, the “\” and “"” characters may be freely used. This restricts single-quoted scalars to printable characters. In addition, it is only possible to break a long single-quoted line where a space character is surrounded by non-spaces.

Example 7.7 Single Quoted Characters

'here''s to "quotes"'"here's to \"quotes\""
  

Legend:

Single-quoted scalars are restricted to a single line when contained inside a implicit key.

Example 7.8 Single Quoted Implicit Keys

'implicit block key' : [ 'implicit flow key' : value, ]{ "implicit block key": [ { "implicit flow key": "value" } ] }
  

Legend:

All leading and trailing white space characters are excluded from the content. Each continuation line must therefore contain at least one non-space character. Empty lines, if any, are consumed as part of the line folding.

Example 7.9 Single Quoted Lines

'·1st non-empty↓ ↓ ·2nd non-empty· →3rd non-empty·'" 1st non-empty\n2nd non-empty 3rd non-empty "
  

Legend:

7.3.3. Plain Style

The plain (unquoted) style has no identifying indicators and provides no form of escaping. It is therefore the most readable, most limited and most context sensitive style. In addition to a restricted character set, a plain scalar must not be empty or contain leading or trailing white space characters. It is only possible to break a long plain line where a space character is surrounded by non-spaces.

Plain scalars must not begin with most indicators, as this would cause ambiguity with other YAML constructs. However, the “:”, “?” and “-indicators may be used as the first character if followed by a non-space “safe” character, as this causes no ambiguity.

Plain scalars must never contain the “:” and “#” character combinations. Such combinations would cause ambiguity with mapping key/value pairs and comments. In addition, inside flow collections, or when used as implicit keys, plain scalars must not contain the “[”, “]”, “{”, “}” and “,” characters. These characters would cause ambiguity with flow collection structures.

Example 7.10 Plain Characters

# Outside flow collection: - ::vector - ": - ()" - Up, up, and away! - -123 - https://example.com/foo#bar # Inside flow collection: - [ ::vector, ": - ()", "Up, up and away!", -123, https://example.com/foo#bar ][ "::vector", ": - ()", "Up, up, and away!", -123, "http://example.com/foo#bar", [ "::vector", ": - ()", "Up, up, and away!", -123, "http://example.com/foo#bar" ] ]
  

Legend:

Plain scalars are further restricted to a single line when contained inside an implicit key.

Example 7.11 Plain Implicit Keys

implicit block key : [ implicit flow key : value, ]{ "implicit block key": [ { "implicit flow key": "value" } ] }
  

Legend:

All leading and trailing white space characters are excluded from the content. Each continuation line must therefore contain at least one non-space character. Empty lines, if any, are consumed as part of the line folding.

Example 7.12 Plain Lines

1st non-empty↓ ↓ ·2nd non-empty· →3rd non-empty"1st non-empty\n2nd non-empty 3rd non-empty"
  

Legend:

7.4. Flow Collection Styles

A flow collection may be nested within a block collection ([FLOW-OUT context]), nested within another flow collection ([FLOW-IN context]) or be a part of an implicit key ([FLOW-KEY context] or [BLOCK-KEY context]). Flow collection entries are terminated by the “,” indicator. The final “,” may be omitted. This does not cause ambiguity because flow collection entries can never be completely empty.

7.4.1. Flow Sequences

Flow sequence content is denoted by surrounding “[” and “]” characters.

Sequence entries are separated by a “,” character.

Example 7.13 Flow Sequence

- [ one, two, ] - [three ,four][ [ "one", "two" ], [ "three", "four" ] ]
  

Legend:

Any flow node may be used as a flow sequence entry. In addition, YAML provides a compact notation for the case where a flow sequence entry is a mapping with a single key/value pair.

Example 7.14 Flow Sequence Entries

[ "double quoted", 'single quoted', plain text, [ nested ], single: pair, ][ "double quoted", "single quoted", "plain text", [ "nested" ], { "single": "pair" } ]
  

Legend:

7.4.2. Flow Mappings

Flow mappings are denoted by surrounding “{” and “}” characters.

Mapping entries are separated by a “,” character.

Example 7.15 Flow Mappings

- { one : two , three: four , } - {five: six,seven : eight}[ { "one": "two", "three": "four" }, { "five": "six", "seven": "eight" } ]
  

Legend:

If the optional “?” mapping key indicator is specified, the rest of the entry may be completely empty.

Example 7.16 Flow Mapping Entries

{ ? explicit: entry, implicit: entry, ?°° }{ "explicit": "entry", "implicit": "entry", null: null }
  

Legend:

Normally, YAML insists the “:” mapping value indicator be separated from the value by white space. A benefit of this restriction is that the “:” character can be used inside plain scalars, as long as it is not followed by white space. This allows for unquoted URLs and timestamps. It is also a potential source for confusion as “a:1” is a plain scalar and not a key/value pair.

Note that the value may be completely empty since its existence is indicated by the “:”.

Example 7.17 Flow Mapping Separate Values

{ unquoted·:·"separate", https://foo.com, omitted value:°, °:·omitted key, }{ "unquoted": "separate", "http://foo.com": null, "omitted value": null, null: "omitted key" }
  

Legend:

To ensure JSON compatibility, if a key inside a flow mapping is JSON-like, YAML allows the following value to be specified adjacent to the “:”. This causes no ambiguity, as all JSON-like keys are surrounded by indicators. However, as this greatly reduces readability, YAML processors should separate the value from the “:” on output, even in this case.

Example 7.18 Flow Mapping Adjacent Values

{ "adjacent":value, "readable":·value, "empty":° }{ "adjacent": "value", "readable": "value", "empty": null }
  

Legend:

A more compact notation is usable inside flow sequences, if the mapping contains a single key/value pair. This notation does not require the surrounding “{” and “}” characters. Note that it is not possible to specify any node properties for the mapping in this case.

Example 7.19 Single Pair Flow Mappings

[ foo: bar ][ { "foo": "bar" } ]
  

Legend:

If the “?” indicator is explicitly specified, parsing is unambiguous and the syntax is identical to the general case.

Example 7.20 Single Pair Explicit Entry

[ ? foo bar : baz ][ { "foo bar": "baz" } ]
  

Legend:

If the “?” indicator is omitted, parsing needs to see past the implicit key to recognize it as such. To limit the amount of lookahead required, the “:” indicator must appear at most 1024 Unicode characters beyond the start of the key. In addition, the key is restricted to a single line.

Note that YAML allows arbitrary nodes to be used as keys. In particular, a key may be a sequence or a mapping. Thus, without the above restrictions, practical one-pass parsing would have been impossible to implement.

Example 7.21 Single Pair Implicit Entries

- [ YAML·: separate ] - [ °: empty key entry ] - [ {JSON: like}:adjacent ][ [ { "YAML": "separate" } ], [ { null: "empty key entry" } ], [ { { "JSON": "like" }: "adjacent" } ] ]
  

Legend:

Example 7.22 Invalid Implicit Keys

[ foo bar: invalid, "foo_...>1K characters..._bar": invalid ]ERROR: - The foo bar key spans multiple lines - The foo...bar key is too long
  

7.5. Flow Nodes

JSON-like flow styles all have explicit start and end indicators. The only flow style that does not have this property is the plain scalar. Note that none of the “JSON-like” styles is actually acceptable by JSON. Even the double-quoted style is a superset of the JSON string format.

Example 7.23 Flow Content

- [ a, b ] - { a: b } - "a" - 'b' - c[ [ "a", "b" ], { "a": "b" }, "a", "b", "c" ]
  

Legend:

A complete flow node also has optional node properties, except for alias nodes which refer to the anchored node properties.

Example 7.24 Flow Nodes

- !!str "a" - 'b' - &anchor "c" - *anchor - !!str°[ "a", "b", "c", "c", "" ]
  

Legend: