解析YAML时忽略日期和时间?

Naf*_*Kay 7 python yaml

我正在编写一个脚本,将一系列YAML文件转换为单个JSON blob.我有一个像这样的YAML文件:

---
AWSTemplateFormatVersion: 2010-09-09
Description: AWS CloudFormation ECS Sample
Parameters:
    - SolrCloudInstanceType:
        Type: String
        Description: Solr Cloud EC2 Instance Type
        Default: m3.2xlarge
Resources:
    - ContainerInstance:
        Type: AWS::EC2::Instance
        Properties:
            InstanceType: m3.xlarge
Run Code Online (Sandbox Code Playgroud)

我正在加载它

import yaml

with open('base.yml', 'rb') as f:
    result = yaml.safe_load(f)
Run Code Online (Sandbox Code Playgroud)

有趣的是,如果我检查一下AWSTemplateFormatVersion,我会得到一个Python datetime.date对象.这会导致我的JSON输出失败:

>>> json.dump(result, sys.stdout, sort_keys=True, indent=4)
{
    "AWSTemplateFormatVersion": Traceback (most recent call last):
  File "./c12n-assemble", line 42, in <module>
    __main__()
  File "./c12n-assemble", line 25, in __main__
    assembler.assemble()
  File "./c12n-assemble", line 39, in assemble
    json.dump(self.__result, self.__output_file, sort_keys=True, indent=4, separators=(',', ': '))
  File "/usr/lib/python2.7/json/__init__.py", line 189, in dump
    for chunk in iterable:
  File "/usr/lib/python2.7/json/encoder.py", line 434, in _iterencode
    for chunk in _iterencode_dict(o, _current_indent_level):
  File "/usr/lib/python2.7/json/encoder.py", line 408, in _iterencode_dict
    for chunk in chunks:
  File "/usr/lib/python2.7/json/encoder.py", line 442, in _iterencode
    o = _default(o)
  File "/usr/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: datetime.date(2010, 9, 9) is not JSON serializable
Run Code Online (Sandbox Code Playgroud)

有没有办法强制YAML解析器不是"聪明"它认为是什么日期或日期+时间只是解析一个字符串?

Dam*_*ers 5

您可以扩展PyYAML加载程序,并删除时间戳或其他类型的隐式标签,如下所示:

class NoDatesSafeLoader(yaml.SafeLoader):
    @classmethod
    def remove_implicit_resolver(cls, tag_to_remove):
        """
        Remove implicit resolvers for a particular tag

        Takes care not to modify resolvers in super classes.

        We want to load datetimes as strings, not dates, because we
        go on to serialise as json which doesn't have the advanced types
        of yaml, and leads to incompatibilities down the track.
        """
        if not 'yaml_implicit_resolvers' in cls.__dict__:
            cls.yaml_implicit_resolvers = cls.yaml_implicit_resolvers.copy()

        for first_letter, mappings in cls.yaml_implicit_resolvers.items():
            cls.yaml_implicit_resolvers[first_letter] = [(tag, regexp) 
                                                         for tag, regexp in mappings
                                                         if tag != tag_to_remove]

NoDatesSafeLoader.remove_implicit_resolver('tag:yaml.org,2002:timestamp')
Run Code Online (Sandbox Code Playgroud)

如下使用此备用加载程序:

>>> yaml.load("2015-03-22 01:49:21", Loader=NoDatesSafeLoader)
'2015-03-22 01:49:21'
Run Code Online (Sandbox Code Playgroud)

供参考,原始行为是:

>>> yaml.load("2015-03-22 01:49:21")
datetime.datetime(2015, 3, 22, 1, 49, 21)
Run Code Online (Sandbox Code Playgroud)