简体   繁体   中英

ruamel.yaml - how to output null instead of !!null '' when default_flow_style=None

Using ruamel.yaml in Python, if I dump with the SafeRepresenter or RoundTripRepresenter and default_flow_style the default, null is represented as expected.

import sys
from ruamel.yaml import YAML
yaml = YAML(typ='rt')
yaml.dump({'key1': None, 'url': 'https://lala/', 'key2': None}, sys.stdout)

key1:
url: https://lala/
key2:

However, if I change the default_flow_style to None, the representer for null seems to be ignored and instead null is represented as.!null '' eg.

import sys
from ruamel.yaml import YAML
yaml = YAML(typ='rt')
yaml.default_flow_style = None
yaml.dump({'key1': None, 'url': 'https://lala/', 'key2': None}, sys.stdout)


key: {key1: !!null '', url: https://lala/, key2: !!null ''}

Setting the representer for null explicitly makes no difference eg

SafeRepresenter.add_representer(type(None), RoundTripRepresenter.represent_none)

I tried the above, but output for null when using the SafeRepresenter instead of the RoundTripRepresenter was still !!null '' when using default_flow_style=None .

How do I output null instead of !!null '' when using default_flow_style=None directly from ruamel.yaml rather than doing postprocessing on its output (eg a find replace)?

I see two possible solutions.

The easiest solution is to use typ='safe' instead of typ='rt' . This is what I generally do, but if you're relying on ruamel.yaml 's ability to preserve things like comments, this isn't an option.

You can create a representer for None values like this:

def represent_none(self, data):
    return self.represent_scalar('tag:yaml.org,2002:null', 'null')

Which will print out your None values as desired:

>>> import sys
>>> from ruamel.yaml import YAML
>>> yaml = YAML(typ='rt')
>>> yaml.default_flow_style = None
>>>
>>> def represent_none(self, data):
...     return self.represent_scalar('tag:yaml.org,2002:null', 'null')
...
>>> yaml.representer.add_representer(type(None), represent_none)
>>> yaml.dump({'key1': None, 'url': 'https://lala/', 'key2': None}, sys.stdout)
{key1: null, url: https://lala/, key2: null}

The round-trip dumper tries to dump None as the empty string, which will not parse back correctly (and at then end of a flow style sequence would be undistinguishable from a sequence with a trailing comma).

The tagged output was the result of the emitter detecting this could not be parsed back, but it is ugly and this is fixed in ruamel.yaml 0.16.13, by emitting null instead of !!null '' , This does not affect block style emitting of None :

import sys
from ruamel.yaml import YAML
yaml = YAML(typ='rt')
yaml.default_flow_style = None
yaml.dump({'key1': None, 'url': 'https://lala/', 'key2': None}, sys.stdout)

which gives:

{key1: null, url: https://lala/, key2: null}

You can get the old behaviour setting yaml.emitter.alt_null = None . You can set that to any value, although choosing one of the other Null Language-Indepenent Type values ( Null , NULL , ~ ) makes the most sense:

import sys
import ruamel.yaml
map = ruamel.yaml.comments.CommentedMap

yaml = ruamel.yaml.YAML()
yaml.emitter.alt_null = '~'
b = map(key1=None, url='https://lala/', key2=None)
b.fa.set_flow_style()
yaml.dump(dict(a=None, b=b), sys.stdout)

which gives:

a:
b: {key1: ~, url: https://lala/, key2: ~}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM