2017-01-23 51 views
2

這個問題很簡單,但要正確地用詞組有點棘手。對YAML文本的Python字典不保留字符

基本上,我有一個具有以下數據字典:

x = { foo: [1, '\n', 'bar'] } 

當我轉換使用pyyaml到YAML與yaml.safe_dump(x, default_flow_style=False)我期望的輸出是:

foo: 
    - 1 
    - '\n' 
    - bar 

然而,我m得到像

foo: 
    - 1 
    - ' 

    ' 
    - bar 

換行字符實際上是在解釋tead被作爲'\ n'字符串傳遞。

我一直在尋找pyyaml文檔,但沒有看到正確的咒語讓這個東西解析正確。

有沒有人處理過同樣的問題?你是如何解決它的?


爲了給出更多的上下文,關於這個。

我有一個json我想轉換爲yaml。

有像這樣的文件:

{ 
    "content": { 
    "Fn::Join": ["\n", [{ "Ref": "parentStackName" }, ""]] 
    } 
} 

最終的結果應該是這樣的:

content: 
    Fn::Join: 
    - "\n" 
    - - Ref: parentStackId 
     - '' 

通知"\n"只是一個字符串在那裏,而不是實際的字符。

我使用的程序是:

  1. 打開文件從文本
  2. 解析JSON與dict
  3. 使用字典轉儲到YAML

當我創建了字典,你可以看到「\ n」作爲字符串的一部分。這是pyyaml轉儲到yaml時發生錯誤的原因。

+0

你顯示的字符串(''\ n'')是一個換行符,而不是一個反斜槓後跟一個文字「N 「,所以你得到的YAML輸出非常有意義。你是否說你想要將諸如換行符這樣的字符轉換爲它們的轉義序列表示?或者你想讓你的字符串爲''\\ n''(文字反斜槓,文字「n」)? – ThisSuitIsBlackNot

+0

該字符串是文字'\ n',而不是換行符。我在這個問題上給了更多的背景。 –

+0

'「\ n」'在JSON字符串中表示一個換行符,而不是一個字面反斜槓,後跟一個字符「n」(參見[spec](http://www.ecma-international.org/publications/files/ECMA -ST/ECMA-404.pdf))。所以你會得到預期的結果。 – ThisSuitIsBlackNot

回答

2

爲了得到你想要的輸出,你可以使用ruamel.yaml往返能力,並更新YAML的JSON子集,用來阻止風格的流式:

import sys 
import ruamel.yaml 
from ruamel.yaml.comments import CommentedMap, CommentedSeq 

# because this is a string and not read from file, you need to escape 
# the backslash in \n 
json_str = """\ 
{ 
    "content": { 
    "Fn::Join": ["\\n", [{ "Ref": "parentStackName" }, ""]] 
    } 
} 
""" 


def block_style(base): 
    """set all mapping and sequneces to block-style""" 
    if isinstance(base, CommentedMap): 
     for k in base: 
      block_style(base[k]) 
     base.fa.set_block_style() 
    if isinstance(base, list): 
     for item in base: 
      block_style(item) 
     base.fa.set_block_style() 
    return base 


data = ruamel.yaml.round_trip_load(json_str) 
block_style(data) 
ruamel.yaml.round_trip_dump(data, sys.stdout) 

給出:

content: 
    Fn::Join: 
    - "\n" 
    - - Ref: parentStackName 
    - '' 

ruamel.yaml是PyYAML的更新版本(免責聲明:我是作者)。它支持YAML 1.2規範(從2009年開始),它使YAML更符合JSON的完整超集,並允許您使用ruamel.yaml解析器(PyYAML僅支持大部分YAML 1.1規範)閱讀您的JSON。

在「往返模式」中,ruamel.yaml的增強包括維護流量響應。基於單獨的組合節點(映射和序列)的塊樣式(以及各種引用樣式,註釋和標籤名稱)。 block_style()所做的是遞歸地將「flow-attribute」.fa更改爲所有複合節點的塊樣式。

+0

優秀,這正是我所需要的。它也保持屬性的順序:)太棒了! –

-1

使用原始字符串當字符串包含特殊字符:

$ cat /tmp/tmp.py 

import yaml 

foo = 'foo' 
x = { foo: [1, r'\n', 'bar'] } 
y = yaml.safe_dump(x, default_flow_style=False) 
print(y) 

$ python3 /tmp/tmp.py 
foo: 
- 1 
- \n 
- bar