Using ruamel.yaml, how can I make vars with NEWLINEs be multiline without quotes

Question:

I am generating YAML which serves as a protocol, and it contains some generated JSON inside of it.

import json
from ruamel import yaml
jsonsample = { "id": "123", "type": "customer-account", "other": "..." }
myyamel = {}
myyamel['sample'] = {}
myyamel['sample']['description'] = "This example shows the structure of the message"
myyamel['sample']['content'] = json.dumps( jsonsample, indent=4, separators=(',', ': '))
print yaml.round_trip_dump(myyamel, default_style = None, default_flow_style=False, indent=2, block_seq_indent=2, line_break=0, explicit_start=True, version=(1,1))

Then I get this output

%YAML 1.1
---
sample:
  content: "{n    "other": "...",n    "type": "customer-account",n    "
  id": "123"n}"
description: This example shows the structure of the message

Now to me that could look much better
if I was able to make the multiline rows be formatted starting with a pipe |

The output that I want to see is this

%YAML 1.1
---
sample:
  content: |
    {    
       "other": "...",
       "type": "customer-account",
       "id": "123"
    }
description: This example shows the structure of the message

See how much easier this is to read …

So how do I solve this in python code ?

Asked By: Tobias Eriksson

||

Answers:

You can do:

import sys
import json
import ruamel.yaml

yaml = ruamel.yaml.YAML()
yaml.version = (1, 1)

jsonsample = { "id": "123", "type": "customer-account", "other": "..." }
myyamel = {}
myyamel['sample'] = {}
myyamel['sample']['description'] = "This example shows the structure of the message"
myyamel['sample']['content'] = json.dumps( jsonsample, indent=4, separators=(',', ': '))

ruamel.yaml.scalarstring.walk_tree(myyamel)

yaml.dump(myyamel, sys.stdout)

which gives:

%YAML 1.1
---
sample:
  description: This example shows the structure of the message
  content: |-
    {
        "id": "123",
        "type": "customer-account",
        "other": "..."
    }

Some notes:

  • since you are using a normal dict the order in which your YAML is printed is implementation and key dependent. If you want the order to be fixed to your assignments use:

      myyamel['sample'] = yaml.comments.CommentedMap()
    
  • you should never use print(yaml.round_trip_dump) if you print the return value, specify the stream to write to, that is more efficient.

  • walk_tree converts all strings that have a newline in them to block style mode recursively. You can also explicitly do:

      myyamel['sample']['content'] = yaml.scalarstring.PreservedScalarString(json.dumps( jsonsample, indent=4, separators=(',', ': ')))
    

in which case you don’t need to call walk_tree()


Even though you are still working on Python 2, you should start getting used to using the print function instead of the print statement. For that include at the top of each of your Python files:

from __future__ import print_function
Answered By: Anthon
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.