Python“;yaml“;从JSON格式转换意外YAML的模块

Python“;yaml“;从JSON格式转换意外YAML的模块,python,json,yaml,Python,Json,Yaml,我试图将JSON数据转换为YAML格式,但得到了意外的YAML输出 使用在线工具将JSON转换为YAML,从而获得预期的YAML输出。但是,当在下面的Python代码中使用相同的JSON时,会得到意想不到的不同结果 import yaml job_template = [

我试图将JSON数据转换为YAML格式,但得到了意外的YAML输出

使用在线工具将JSON转换为YAML,从而获得预期的YAML输出。但是,当在下面的Python代码中使用相同的JSON时,会得到意想不到的不同结果

import yaml                                                                     

job_template = [                                                                
  {                                                                             
    "job-template": {                                                           
      "name": "{name}_job",                                                     
      "description": "job description",                                         
      "project-type": "multibranch",                                            
      "number-to-keep": 30,                                                     
      "days-to-keep": 30,                                                       
      "scm": [                                                                  
        {                                                                       
          "git": {                                                              
            "url": "{git_url}"                                                  
          }                                                                     
        }                                                                       
      ]                                                                         
    }                                                                           
  }                                                                             
]                                                                               

yaml.dump(job_template, open("job_template.yaml", "w"))   
需要以下YAML数据:

- job-template:
    name: "{name}_job"
    description: job description
    project-type: multibranch
    number-to-keep: 30
    days-to-keep: 30
    scm:
    - git:
        url: "{git_url}"
获取以下YAML格式:

 - job-template:
     days-to-keep: 30
     description: job description
     name: '{name}_job'
     number-to-keep: 30
     project-type: multibranch
     scm:
     - git: {url: '{git_url}'}

使用
default\u flow\u style=False

Ex:

import yaml                                                                     

job_template = [                                                                
  {                                                                             
    "job-template": {                                                           
      "name": "{name}_job",                                                     
      "description": "job description",                                         
      "project-type": "multibranch",                                            
      "number-to-keep": 30,                                                     
      "days-to-keep": 30,                                                       
      "scm": [                                                                  
        {                                                                       
          "git": {                                                              
            "url": "{git_url}"                                                  
          }                                                                     
        }                                                                       
      ]                                                                         
    }                                                                           
  }                                                                             
]                                                                               

yaml.dump(job_template, open("job_template.yaml", "w"), default_flow_style=False)  

问题出在Python代码中:
dict
是一个无序的容器
pprint
只给出与yaml输出相同的顺序:

>>> pprint.pprint(job_template)
[{'job-template': {'days-to-keep': 30,
                   'description': 'job description',
                   'name': '{name}_job',
                   'number-to-keep': 30,
                   'project-type': 'multibranch',
                   'scm': [{'git': {'url': '{git_url}'}}]}}]

如果问题是关于最后一级dict的表示方式,{code>{“url”:“{git_url}},答案已由

给出,首先您应该将作业模板保留在JSON文件中,例如
input.JSON

[                                                                
  {                                                                             
    "job-template": {                                                           
      "name": "{name}_job",                                                     
      "description": "job description",                                         
      "project-type": "multibranch",                                            
      "number-to-keep": 30,                                                     
      "days-to-keep": 30,                                                       
      "scm": [                                                                  
        {                                                                       
          "git": {                                                              
            "url": "{git_url}"                                                  
          }                                                                     
        }                                                                       
      ]                                                                         
    }                                                                           
  }                                                                             
]
这样,您可以更轻松地调整脚本以处理不同的文件。这样做 还可以保证JSON对象中的键是有序的,这在代码中包含JSON作为dicts和list时是不保证的,至少对于所有当前版本的Python是不保证的

因为YAML 1.2(2009年发布的规范)是 YAML,您可以只使用一个YAML 1.2库来保留密钥顺序 加载转储时,请将其转换为所需的格式。自从 PyYAML仍然停留在2005年发布的YAML 1.1规范上,您知道吗 不能使用它,但您可以使用
ruamel.yaml
(免责声明我是 该软件包的作者)

唯一的“问题”是
ruamel.yaml
也会保留 (流)输入的样式。这正是你不想要的

因此,您必须递归地遍历数据结构并更改 包含该信息的属性:

import sys
import ruamel.yaml

def block_style(d):
    if isinstance(d, dict):
        d.fa.set_block_style()
        for key, value in d. items():
            try:
                if '{' in value:
                    d[key] = ruamel.yaml.scalarstring.DoubleQuotedScalarString(value)
            except TypeError:
                pass
            block_style(value)
    elif isinstance(d, list):
        d.fa.set_block_style()
        for elem in d:
            block_style(elem)

yaml = ruamel.yaml.YAML()

with open('input.json') as fp:
    data = yaml.load(fp)

block_style(data)

yaml.dump(data, sys.stdout)
其中:

- job-template:
    name: "{name}_job"
    description: job description
    project-type: multibranch
    number-to-keep: 30
    days-to-keep: 30
    scm:
    - git:
        url: "{git_url}"
上述方法同样适用于Python2和Python3


的额外代码测试{
是在不能表示为普通标量的字符串周围强制使用双引号。默认情况下,
ruamel.yaml
将使用单引号标量,前提是不需要yaml双引号标量中的额外转义序列来表示字符串。

PyYAML中顺序的更改是对tri进行取整的障碍p对YAML文件的编辑和许多其他解析器都试图解决这个问题

一个值得一看的是,它在其上写道:

作者提供的代码示例演示了这一点:

import sys
import ruamel.yaml as yaml

yaml_str = """\
3: abc
conf:
    10: def
    3: gij     # h is missing
more:
- what
- else
"""

data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
data['conf'][10] = 'klm'
data['conf'][3] = 'jig'
yaml.dump(data, sys.stdout, Dumper=yaml.RoundTripDumper)
will give you:

3: abc
conf:
  10: klm
  3: jig       # h is missing
more:
- what
- else

对此进行了更全面的讨论。它被描述为PyYAML的替代品,因此应该很容易在您的环境中进行实验。

这个结果实际上是怎么不正确的?它包含所有信息,并且是一个正确的yaml格式。@Brunodesshuilliers结果并不错误,这是意外的。
import sys
import ruamel.yaml as yaml

yaml_str = """\
3: abc
conf:
    10: def
    3: gij     # h is missing
more:
- what
- else
"""

data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
data['conf'][10] = 'klm'
data['conf'][3] = 'jig'
yaml.dump(data, sys.stdout, Dumper=yaml.RoundTripDumper)
will give you:

3: abc
conf:
  10: klm
  3: jig       # h is missing
more:
- what
- else