2017-01-23 9 views
2

Вопрос прост, но немного сложный для фразы правильно.Python dict to YAML text не сохраняет символы

В принципе, у меня есть словарь, который имеет следующие данные:

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

Когда я конвертировать в YAML, используя PyYAML с yaml.safe_dump(x, default_flow_style=False) Я ожидаю, что выход будет:

foo: 
    - 1 
    - '\n' 
    - bar 

однако, я m получить что-то вроде

foo: 
    - 1 
    - ' 

    ' 
    - bar 

Символ новой строки фактически интерпретируется ins который передается как строка «\ n».

Я смотрел документацию на pyyaml, но не видел правильных заклинаний, чтобы правильно разобрать эту штуку.

Кто-нибудь имел дело с этим же вопросом раньше? Как вы его решили?


Чтобы больше контекста, об этом.

У меня есть json Я хочу конвертировать в yaml.

Файл, который имеет что-то вроде этого:

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

конечный результат должен быть таким:

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

Обратите внимание на "\n" это просто строка там, а не фактический характер.

Процедура я использую:

  1. Открыть файл
  2. Анализировать JSON из текста в Сыроватского
  3. Используйте Dict сваливать в YAML

Когда я создаю Dict, вы можете увидеть «\ n» как часть строки. Это когда пийамль сбрасывает это в ямль, что все идет вразрез.

+0

Строка вы показали (' '\ n'') является символ новой строки, а не обратной косой черты, за которыми следует«п », поэтому вывод YAML, который вы получаете, имеет прекрасный смысл. Вы говорите, что хотите преобразовать символы, такие как newline, в их представления escape-последовательности? Или вы хотите, чтобы ваша строка была '' \\ 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 и обновления потока стиля, что JSON подмножество YAML использует для блокировки стиля:

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 и позволяет вам читать ваш JSON с помощью парсера ruamel.yaml (PyYAML поддерживает только большую часть спецификации YAML 1.1).

В режиме «round-trip-mode» усовершенствования ruamel.yaml включают в себя поддержание потока - соответственно.блочный стиль составных узлов (сопоставлений и последовательностей) на индивидуальной основе (а также различные стили цитирования, комментарии и имена тегов). То, что block_style() делает, рекурсивно изменяет «атрибут потока» .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