Search code examples
pythonmappingyamlliteralspyyaml

Literals in a mapping of mappings in YAML


How is it possible to create a literal within a mapping of mappings using YAML?

I am trying to put literals in a mapping of mappings in YAML using PyYAML. Based on YAML specs a mapping of mappings is realized with:

Mark McGwire: {hr: 65, avg: 0.278}
Sammy Sosa: {
    hr: 63,
    avg: 0.288
  }

while a literal conserving the line breaks is done with:

stats: |
  63 Home Runs
  0.288 Batting Average

Now I am trying to combine literals with a mapping of mappings like so:

Sammy Sosa: {
    hr: 63,
    avg: 0.288,
    stats: |
  63 Home Runs
  0.288 Batting Average
  }

and get the error thrown:

yaml.scanner.ScannerError: while scanning for the next token
found character '|' that cannot start any token
  in "test.yml", line 4, column 12

Is there another way or work around of putting litterals inside mappings of mappings in YAML?


Solution

  • Your "literal" is more officially called a literal block style scalar. Apart from block style there is flow style. You are using the flow style for the value associated with the key Sammy Sosa.

    Within flow style you are not allowed to have block style

    YAML allows flow nodes to be embedded inside block collections (but not vice-versa).

    , but that is what you try to do with the value for the key stats. Apart from that, you also did not indent the literal scalar enough.

    Change the flow style mapping into block style, by removing the matching {, } and trailing ,. Align the keys (required in block style) and indent the literal scalar appropriately (i.e. more than the beginning column of stats).

    This is valid YAML and equivalent to what you wanted to achieve:

    Sammy Sosa:
      hr: 63
      avg: 0.288
      stats: |
        63 Home Runs
        0.288 Batting Average
    

    Your first example flow style mapping within block style mapping can also be rewritten as block style mapping within block style mapping as follows:

    Mark McGwire: 
      hr: 65
      avg: 0.278
    Sammy Sosa: 
      hr: 63
      avg: 0.288
    

    For this purpose there is no difference, but you should also be aware that you are using the YAML 1.2 specification (from 2009), but the PyYAML library for Python only supports most of the older YAML 1.1 (from 2005).