在 json 嵌入式 YAML 文件中 - 使用 Python 仅替换 json 值
In a json embedded YAML file - replace only json values using Python
我有一个 YAML 文件如下:
api: v1
hostname: abc
metadata:
name: test
annotations: {
"ip" : "1.1.1.1",
"login" : "fad-login",
"vip" : "1.1.1.1",
"interface" : "port1",
"port" : "443"
}
我正在尝试从文件中读取此数据,仅替换 ip
和 vip
的值并将其写回文件。
我试过的是:
open ("test.yaml", w) as f:
yaml.dump(object, f) #this does not help me since it converts the entire file to YAML
还有 json.dump()
也不起作用,因为它将整个文件转换为 JSON。它需要采用相同的格式,但需要更新值。我该怎么做?
你拥有的不是嵌入了 JSON 的 YAML,它是 YAML annotations
的一些值
采用 YAML 流样式(它是 JSON 的超集,因此与它非常相似)。
这将是
嵌入了 YAML JSON:
api: v1
hostname: abc
metadata:
name: test
annotations: |
{
"ip" : "1.1.1.1",
"login" : "fad-login",
"vip" : "1.1.1.1",
"interface" : "port1",
"port" : "443"
}
此处 annotations
的值是一个字符串,您可以将其传递给 JSON 解析器。
您可以只加载文件,修改它并转储。这将改变布局
flow-style 部分,但这不会影响任何以下解析器:
import sys
import ruamel.yaml
file_in = Path('input.yaml')
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.width = 1024
data = yaml.load(file_in)
annotations = data['metadata']['annotations']
annotations['ip'] = type(annotations['ip'])('4.3.2.1')
annotations['vip'] = type(annotations['vip'])('1.2.3.4')
yaml.dump(data, sys.stdout)
给出:
api: v1
hostname: abc
metadata:
name: test
annotations: {"ip": "4.3.2.1", "login": "fad-login", "vip": "1.2.3.4", "interface": "port1", "port": "443"}
type(annotations['vip'])()
确定输出中的替换字符串具有相同的
引用原文。
ruamel.yaml
目前不保留流样式中的换行符 mapping/sequence。
如果这必须以最小的机会返回到某个存储库,您可以这样做:
import sys
import ruamel.yaml
file_in = Path('input.yaml')
def rewrite_closing_curly_brace(s):
res = []
for line in s.splitlines():
if line and line[-1] == '}':
res.append(line[:-1])
idx = 0
while line[idx] == ' ':
idx += 1
res.append(' ' * (idx - 2) + '}')
continue
res.append(line)
return '\n'.join(res) + '\n'
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.width = 15
data = yaml.load(file_in)
annotations = data['metadata']['annotations']
annotations['ip'] = type(annotations['ip'])('4.3.2.1')
annotations['vip'] = type(annotations['vip'])('1.2.3.4')
yaml.dump(data, sys.stdout, transform=rewrite_closing_curly_brace)
给出:
api: v1
hostname: abc
metadata:
name: test
annotations: {
"ip": "4.3.2.1",
"login": "fad-login",
"vip": "1.2.3.4",
"interface": "port1",
"port": "443"
}
此处的 15
宽度当然高度依赖于您的文件,如果它们可能会影响其他行
更长。在那种情况下,您可以将其省略,然后进行包装
rewrite_closing_curly_brace()
确实拆分并缩进了整个流样式部分。
请注意,您的原始输出和转换后的输出是无效的 YAML,
为了向后兼容,ruamel.yaml
接受了它。根据 YAML
规范右大括号应比 annotation
的开头缩进更多
我有一个 YAML 文件如下:
api: v1
hostname: abc
metadata:
name: test
annotations: {
"ip" : "1.1.1.1",
"login" : "fad-login",
"vip" : "1.1.1.1",
"interface" : "port1",
"port" : "443"
}
我正在尝试从文件中读取此数据,仅替换 ip
和 vip
的值并将其写回文件。
我试过的是:
open ("test.yaml", w) as f:
yaml.dump(object, f) #this does not help me since it converts the entire file to YAML
还有 json.dump()
也不起作用,因为它将整个文件转换为 JSON。它需要采用相同的格式,但需要更新值。我该怎么做?
你拥有的不是嵌入了 JSON 的 YAML,它是 YAML annotations
的一些值
采用 YAML 流样式(它是 JSON 的超集,因此与它非常相似)。
这将是 嵌入了 YAML JSON:
api: v1
hostname: abc
metadata:
name: test
annotations: |
{
"ip" : "1.1.1.1",
"login" : "fad-login",
"vip" : "1.1.1.1",
"interface" : "port1",
"port" : "443"
}
此处 annotations
的值是一个字符串,您可以将其传递给 JSON 解析器。
您可以只加载文件,修改它并转储。这将改变布局 flow-style 部分,但这不会影响任何以下解析器:
import sys
import ruamel.yaml
file_in = Path('input.yaml')
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.width = 1024
data = yaml.load(file_in)
annotations = data['metadata']['annotations']
annotations['ip'] = type(annotations['ip'])('4.3.2.1')
annotations['vip'] = type(annotations['vip'])('1.2.3.4')
yaml.dump(data, sys.stdout)
给出:
api: v1
hostname: abc
metadata:
name: test
annotations: {"ip": "4.3.2.1", "login": "fad-login", "vip": "1.2.3.4", "interface": "port1", "port": "443"}
type(annotations['vip'])()
确定输出中的替换字符串具有相同的
引用原文。
ruamel.yaml
目前不保留流样式中的换行符 mapping/sequence。
如果这必须以最小的机会返回到某个存储库,您可以这样做:
import sys
import ruamel.yaml
file_in = Path('input.yaml')
def rewrite_closing_curly_brace(s):
res = []
for line in s.splitlines():
if line and line[-1] == '}':
res.append(line[:-1])
idx = 0
while line[idx] == ' ':
idx += 1
res.append(' ' * (idx - 2) + '}')
continue
res.append(line)
return '\n'.join(res) + '\n'
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.width = 15
data = yaml.load(file_in)
annotations = data['metadata']['annotations']
annotations['ip'] = type(annotations['ip'])('4.3.2.1')
annotations['vip'] = type(annotations['vip'])('1.2.3.4')
yaml.dump(data, sys.stdout, transform=rewrite_closing_curly_brace)
给出:
api: v1
hostname: abc
metadata:
name: test
annotations: {
"ip": "4.3.2.1",
"login": "fad-login",
"vip": "1.2.3.4",
"interface": "port1",
"port": "443"
}
此处的 15
宽度当然高度依赖于您的文件,如果它们可能会影响其他行
更长。在那种情况下,您可以将其省略,然后进行包装
rewrite_closing_curly_brace()
确实拆分并缩进了整个流样式部分。
请注意,您的原始输出和转换后的输出是无效的 YAML,
为了向后兼容,ruamel.yaml
接受了它。根据 YAML
规范右大括号应比 annotation