如何使用ruamel.yaml输出行分隔/格式化的json块?

问题描述 投票:0回答:1

我目前正在将此代码块与 pyyaml 一起使用,但我想用 ruamel.yaml 完成同样的事情

import yaml
import json
envList=envList={"env":"development", "region":"us", "tag":"latest", "kubesvcname":"service", "containername":"testcontainer", "namespace":"kubens", "buildid":"1000"}
jsonFile = json.dumps(envList, indent=4)
configMapHeader={ \
    "apiVersion": "v1", \
    "kind":"ConfigMap", \
    "metadata": { \
        "name": f'{envList["kubesvcname"]}_{envList["containername"]}-{envList["tag"]}-{envList["buildid"]}', \
        "namespace": f'{envList["namespace"]}'\
    },
    "data":{"appsettings.json": \
             jsonFile }
}

def str_presenter(dumper, data):
    """configures yaml for dumping multiline strings
    Ref: https://stackoverflow.com/questions/8640959/how-can-i-control-what-scalar-form-pyyaml-uses-for-my-data"""
    if len(data.splitlines()) > 1:  # check for multiline string
        return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
    return dumper.represent_scalar('tag:yaml.org,2002:str', data)


yaml.representer.SafeRepresenter.add_representer(str, str_presenter) 
print(yaml.safe_dump(configMapHeader, sort_keys=False, line_break=True))

其输出看起来像这样:

apiVersion: v1
kind: ConfigMap
metadata:
  name: service_testcontainer-latest-1000
  namespace: kubens
data:
  appsettings.json: |-
    {
        "env": "development",
        "region": "us",
        "tag": "latest",
        "kubesvcname": "service",
        "containername": "testcontainer",
        "namespace": "kubens",
        "buildid": "1000"
    }

当我尝试用 ruamel.yaml 做类似的事情时,我得到了 输出文件中的换行符。

这是代码:

def initYamlParser():
    import ruamel.yaml as yaml
    yaml = yaml.YAML()
    yaml.preserve_quotes = True
    yaml.explicit_start = True
    return yaml

import sys
import json
yaml=initYamlParser()
envList=envList={"env":"development", "region":"us", "tag":"latest", "kubesvcname":"service", "containerver": "latest", "containername":"testcontainer", "namespace":"kubens", "buildid":"1000"}
jsonFile = json.dumps(envList, indent=4)
configMapHeader={ \
    "apiVersion": "v1", \
    "kind":"ConfigMap", \
    "metadata": { \
        "name": f'{envList["kubesvcname"]}_{envList["containername"]}-{envList["containerver"]}-{envList["buildid"]}', \
        "namespace": f'{envList["namespace"]}'\
    },
    "data":{"appsettings.json": \
            jsonFile }
}
print(configMapHeader)
with open("file.yaml", 'w+') as file:
    yaml.dump(configMapHeader, file)

这是输出:

apiVersion: v1
kind: ConfigMap
metadata:
  name: service_testcontainer-latest-1000
  namespace: kubens
data:
  appsettings.json: "{\n    \"env\": \"development\",\n    \"region\": \"us\",\n \
    \   \"tag\": \"latest\",\n    \"kubesvcname\": \"service\",\n    \"containerver\"\
    : \"latest\",\n    \"containername\": \"testcontainer\",\n    \"namespace\": \"\
    kubens\",\n    \"buildid\": \"1000\"\n}"

Ruamel.yaml 不支持 str_presenter,所以我希望有一个该函数的 ruamel.yaml 兼容版本,或者一种使用 ruamel.yaml 在内部呈现它的方法

python json pyyaml ruamel.yaml
1个回答
0
投票

首先,转储 YAML 文档时通常不应附加到文件。自从

ruamel.yaml
将 UTF-8 写入文件,将其打开为
"wb"

您设置了

yaml.preserve_quotes = True
,但这仅在您往返时有效(加载 YAML,然后转储它)。

然后在

ruamel.yaml
中,您也可以拥有不同的表示者,只需将其附加到
representer
属性(这是
Representer
属性,默认为
RoundTripRepresenter
)。唯一的区别是它传递一个代表作为第一个参数:

import sys
import json
import ruamel.yaml
   
yaml = ruamel.yaml.YAML()
yaml.explicit_start = True

def str_presenter(cls, data):
    if len(data.splitlines()) > 1:  # check for multiline string
        return cls.represent_scalar('tag:yaml.org,2002:str', data, style='|')
    return cls.represent_scalar('tag:yaml.org,2002:str', data)

yaml.representer.add_representer(str, str_presenter)

envList={"env":"development", "region":"us", "tag":"latest", "kubesvcname":"service", "containerver": "latest", "containername":"testcontainer", "namespace":"kubens", "buildid":"1000"}
jsonFile = json.dumps(envList, indent=4)
configMapHeader={ \
    "apiVersion": "v1", \
    "kind":"ConfigMap", \
    "metadata": { \
        "name": f'{envList["kubesvcname"]}_{envList["containername"]}-{envList["containerver"]}-{envList["buildid"]}', \
        "namespace": f'{envList["namespace"]}'\
    },
    "data":{"appsettings.json": \
            jsonFile }
}
 

# print(data)
yaml.dump(configMapHeader, sys.stdout)

给出:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: service_testcontainer-latest-1000
  namespace: kubens
data:
  appsettings.json: |-
    {
        "env": "development",
        "region": "us",
        "tag": "latest",
        "kubesvcname": "service",
        "containerver": "latest",
        "containername": "testcontainer",
        "namespace": "kubens",
        "buildid": "1000"
    }

如果您加载预期的输出然后转储它,您可以看到

ruamel.yaml
可以保留块样式文字标量。 通过检查键
appsetting.json
的值,您将看到这是
LiteralScalarString
类的实例。 该知识可用于仅以这种方式转储一个标量(而不是所有嵌入换行符的标量):

import sys
import json
import ruamel.yaml
   
yaml = ruamel.yaml.YAML()
yaml.explicit_start = True

envList={"env":"development", "region":"us", "tag":"latest", "kubesvcname":"service", "containerver": "latest", "containername":"testcontainer", "namespace":"kubens", "buildid":"1000"}
jsonFile = json.dumps(envList, indent=4)
configMapHeader={ \
    "apiVersion": "v1", \
    "kind":"ConfigMap", \
    "metadata": { \
        "name": f'{envList["kubesvcname"]}_{envList["containername"]}-{envList["containerver"]}-{envList["buildid"]}', \
        "namespace": f'{envList["namespace"]}'\
    },
    "data":{"appsettings.json": \
            ruamel.yaml.scalarstring.LiteralScalarString(jsonFile) }
}

yaml.dump(configMapHeader, sys.stdout)

给出:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: service_testcontainer-latest-1000
  namespace: kubens
data:
  appsettings.json: |-
    {
        "env": "development",
        "region": "us",
        "tag": "latest",
        "kubesvcname": "service",
        "containerver": "latest",
        "containername": "testcontainer",
        "namespace": "kubens",
        "buildid": "1000"
    }
  • 您可能想看看
    envList=envList=....
    ,不知道为什么为同一个变量分配两次
  • 如果您想知道:您会在文字标量指示器后面看到一个破折号
    |-
    ,因为 JSON 转储器输出不包括 最后的换行符
© www.soinside.com 2019 - 2024. All rights reserved.