en-US/about_YamlEmitting.help.txt

TOPIC
    about_yamlemitting
 
SHORT DESCRIPTION
    YAML documents can express quite complex structures and the rules `Yayaml`
    uses to build these structures tries to be as intuitive as possible. This
    guide will outline these behaviours and provide more information on how to
    adjust them.
 
LONG DESCRIPTION
Schemas
    Schemas are a new feature added in YAML 1.2 and is designed to contain the
    rules on how values are emitted in YAML documents. There are 4 schemas that
    have been implemented in this module:
    + `Yaml12` - Default
    YAML 1.2 Core Schema
    . + `Yaml12JSON` -
    YAML 1.2 JSON Schema
    + `Yaml11` -
    YAML 1.1 Tags
    + `Blank` -
    YAML 1.2 Failsafe Schema
    Use the `-Schema ...` parameter, i.e `-Schema Yaml11`, to use a different
    schema when emitting a YAML string. It is also possible to use a custom
    schema from scratch or by extending an existing one using the
    New-YamlSchema
    cmdlet. A schema can be used when emitting a YAML string to:
    + Change was values are treated as scalars if they don't match the existing
    rules + Change how scalar values are emitted, either by adjusting the raw
    string, setting a tag, or changing the style + Change how map values are
    emitted, either by adjusting the map contents or changing the style + Change
    how sequence values are emitted, either by adjusting the sequence contents
    or changing the style
    The
    New-YamlSchema
    cmdlet documents a few examples for these parameters and how they can be
    used.
 
Scalar Values
    Currently the following types are treated as scalar values:
    + `[bool]` - emitted as `true` or `false` + `[char]` - emitted as a string +
    `[DateTime]` - The YAML 1.1 schema emits this using the 1.1 timestamp rules,
    YAML 1.2 and 1.2 JSON will emit using the `ToString("o")` format +
    `[DateTimeOffset]` - Same as `[DateTimeOffset]` + `[Guid]` - emitted as the
    GUID value + `[string]` - emitted as a string + `[sbyte], [byte], [int16],
    [uint16], [int32], [uint32], [int64], [uint64],
    [System.Numerics.BigInteger]` - emitted as an integer + `[float], [double],
    [decimal]` - emitted as a float with a significand, base, and exponent
    A scalar value can be emitted with the following styles:
    |Style|Example| |-|-| |Any|Schema default| |Plain|`foo: value`|
    |SingleQuoted|`foo: 'value'`| |DoubleQuoted|`foo: "value"`| |Literal|`foo:
    |\n value`| |Folded|`foo: >\n value`|
    The
    Add-YamlFormat
    cmdlet can be used to apply a custom style to a specific object.
 
Map and Sequence Values
    Map values are dictionary like values and sequence values are list like
    values. Any type that implements `[System.Collections.IList]` will be
    treated as a sequence. Any type that implements
    `[System.Collections.IDictionary]` will use the dictionary key value pairs
    as the map. All other types that aren't scalars or sequences will also be
    treated as maps. The instance's properties will be used as the key value
    pair as the maps contents.
    A map and sequence value can be emitted with the following styles:
    |Style|Example| |-|-| |Any|Schema default| |Block|`foo: bar` - `- 1\n- 2`|
    |Flow|`{foo: bar}` - `[1, 2]`|
    The
    Add-YamlFormat
    cmdlet can be used to apply a custom style to a specific object.
 
Null Keys
    It is possible for a YAML map/dict value to contain a null value as a key.
    Unfortunately the builtin dictionary types in dotnet do not allow `$null` to
    be used as a key. An alternative is to use `[Yayaml.NullKey]::Value` to
    represent a null key.
 
    ConvertTo-Yaml @{
        [Yayaml.NullKey]::Value = 'abc'
    }
 
    null: abc
 
Comments
    It is possible to emit comments alongside an object when using
    `ConvertTo-Yaml`. Comments cannot be parsed through `ConvertFrom-Yaml`, the
    only way to emit a comment is by explicitly adding it to the object metadata
    before calling `ConvertTo-Yaml`. Comments come in three forms:
    + Pre - Added on the preceding line of the value + Inline - Added at the end
    of the line of the value + Post - Added on the next line of the value
    Each of these comments can be added through the
    Add-YamlFormat
    cmdlet through the `-PreComment`, `-Comment`, and `-PostComment` parameters respectively.
    Due to the YAML parsing rules, there are some cases where comments may not
    be supported, for example:
    + Folded or Literal scalar values cannot have an inline comment + Flow
    maps/sequences (dicts/lists) will ingore any comments in any child values,
    the map/sequence itself can still have a pre, inline, and post comment
    though + Block maps/sequences cannot have an inline comment, the comment
    should be set on the inner value that is desired instead + Map (dicts) keys
    cannot have comments applied, they should be set on the value instead
    Here is an example of how a pre, inline, and post comment works on a simple
    scalar value:
 
    $value = 'value' | Add-YamlFormat -PreComment pre -Comment inline -PostComment post -PassThru
    $value | ConvertTo-Yaml
 
    # pre
    value # inline
    # post
 
    Attempting to set an inline comment on a folded or literal scalar will emit
    a warning
 
    $value = 'value' | Add-YamlFormat -PreComment pre -Comment inline -PostComment post -PassThru -ScalarStyle Literal
    $value | ConvertTo-Yaml
    # WARNING: Scalar value 'value' has a style of Literal and contained inline comment but will be ignored. Inline comment cannot be used for the Folded or Literal scalar values.
 
    # pre
    |-
      value
    # post
 
    The same logic applies when serializing a scalar value inside a map or
    sequence.
 
    $value = [Ordered]@{
        Map = [Ordered]@{
            First = 'first'
            Key = 'value' | Add-YamlFormat -PreComment pre -Comment inline -PostComment post -PassThru
            Last = 'last'
        }
        Sequence = @(
            'first'
            'value' | Add-YamlFormat -PreComment pre -Comment inline -PostComment post -PassThru
            'last'
        )
    }
    $value | ConvertTo-Yaml
 
    Map:
      First: first
      # pre
      Key: value # inline
      # post
      Last: last
    Sequence:
    - first
    # pre
    - value # inline
    # post
    - last
 
    When adding a comment to a map/dict value itself, it can contain a pre and
    post comment but not an inline comment. For example this is how the pre/post
    comments work alongside a key that also has a pre/post comment.
 
    $value = [Ordered]@{
        First = 'value' | Add-YamlFormat -PreComment "value pre" -PostComment "value post" -PassThru
    }
    $value | Add-YamlFormat -PreComment "map pre" -PostComment "map post"
    $value | ConvertTo-Yaml
 
    # map pre
    # value pre
    First: value
    # value post
    # map post
 
    A flow map/dict will ignore any comments in the child values but can have an
    inline comment on it. The comment rules work similar to a scalar value where
    the inline comment comes after the flow map.
 
    $value = [Ordered]@{
        First = 'value' | Add-YamlFormat -PreComment "value pre" -Comment "value inline" -PostComment "value post" -PassThru
    }
    $value | Add-YamlFormat -PreComment "map pre" -Comment "map inline" -PostComment "map post" -CollectionStyle Flow
    $value | ConvertTo-Yaml
 
    # map pre
    {First: value} # map inline
    # map post
 
    The same restrictions also apply to sequences where a block sequence cannot
    have an inline comment while flow sequences will ignore any comment inside
    the sequence itself.
 
    $block = @(
        'first'
        'value block' | Add-YamlFormat -PreComment "value block pre" -Comment "value block inline" -PostComment "value block post" -PassThru
        'last'
    )
    Add-YamlFormat -InputObject $block -PreComment "block pre" -PostComment "block post"
     
    $flow = @(
        'first'
        'value flow' | Add-YamlFormat -PreComment "value flow pre" -Comment "value flow inline" -PostComment "value flow post" -PassThru
        'last'
    )
    Add-YamlFormat -InputObject $flow -PreComment "flow pre" -Comment "flow inline" -PostComment "flow post" -CollectionStyle Flow
    $value = [Ordered]@{ Block = $block; Flow = $flow }
    ConvertTo-Yaml $value
 
    # block pre
    Block:
    - first
    # value block pre
    - value block # value block inline
    # value block post
    - last
    # block post
    # flow pre
    Flow: [first, value flow, last] # flow inline
    # flow post
 
    If you wish to apply a comment to all instances of a specific type, you can
    combine custom schema emit transformer with `Add-YamlFormat` to add the
    comment. For example:
 
    class MyClass {
        [int]$Id
        [string]$Title
        [Object]$MetaData
    }
     
    $schema = New-YamlSchema -EmitTransformer {
        param ($Value, $Schema)
     
        if ($Value -is [MyClass]) {
            $meta = $Value.MetaData | Add-YamlFormat -Comment "type: $($Value.MetaData.GetType().Name)" -PassThru
            $obj = [Ordered]@{
                Title = $Value.Title
                MetaData = $meta
            }
            $obj | Add-YamlFormat -PreComment "id: $($Value.Id)"
     
            $obj
        }
        else {
            $Schema.EmitTransformer($Value)
        }
    }
     
    @(
        [MyClass]@{
            Id = 1
            Title = 'Foo'
            MetaData = 'meta'
        }
        [MyClass]@{
            Id = 2
            Title = 'Bar'
            MetaData = 1
        }
    ) | ConvertTo-Yaml -Schema $schema
 
    # id: 1
    - Title: Foo
      MetaData: meta # type: String
    # id: 2
    - Title: Bar
      MetaData: 1 # type: Int32
 
    In the above example we use a custom transformer to emit the `Id` property
    as a pre comment and add the .NET type name of the `MetaData` value as an
    inline comment. As the transformer is run on each instance to serialize, it
    will do this transformation on any instance of that type, whether it's a
    root value or part of an inner map/sequence.