python - 如何使用 Go 和 Python 处理 YAML 中的十六进制值?

标签 python go yaml

我有一个简单的以下程序:

package main

import (
    "fmt"

    yaml "gopkg.in/yaml.v2"
)

type Test struct {
    SomeStringWithQuotes string `yaml:"someStringWithQuotes"`
    SomeString           string `yaml:"someString"`
    SomeHexValue         string `yaml:"someHexValue"`
}

func main() {
    t := Test{
        SomeStringWithQuotes: "\"Hello World\"",
        SomeString:           "Hello World",
        SomeHexValue:         "0xDef9C64256DeE61ebf5B212238df11C7E532e3B7",
    }
    yamlBytes, _ := yaml.Marshal(t)
    fmt.Print(string(yamlBytes))
}

这会打印以下内容,并清楚地表明 Go 会决定何时引用字符串或不引用字符串:

someStringWithQuotes: '"Hello World"'
someString: Hello World
someHexValue: 0xDef9C64256DeE61ebf5B212238df11C7E532e3B7

但是,当我尝试使用以下 Python 脚本读取此 YAML 时:

import yaml

yaml_str = """
someStringWithQuotes: '"Hello World"'
someString: Hello World
someHexValue: 0xDef9C64256DeE61ebf5B212238df11C7E532e3B7
"""

print(yaml.load(yaml_str))

它将十六进制值解析为整数。如果我现在使用以下代码序列化回 YAML:

import yaml
import sys

yaml_str = """
someStringWithQuotes: '"Hello World"'
someString: Hello World
someHexValue: 0xDef9C64256DeE61ebf5B212238df11C7E532e3B7
"""

print(yaml.dump(yaml.load(yaml_str)))

我得到:

someHexValue: 1272966107484048169783147972546098614451903325111
someString: Hello World
someStringWithQuotes: '"Hello World"'

如何才能最好地确保保留十六进制格式?不幸的是,我个人对 Go 端的代码没有任何影响(但是对于尝试做类似事情的其他人来说,Go 端解决方案仍然是受欢迎的)。

最佳答案

您可以在 Python 中加载和转储该输出,同时使用 ruamel.yaml 保留十六进制值(免责声明:我是该 Python 包的作者):

import sys
import ruamel.yaml

yaml_str = """\
someHexValue: 0xDef9C64256DeE61ebf5B212238df11C7E532e3B7
someString: Hello World
someStringWithQuotes: '"Hello World"'
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

给出:

someHexValue: 0xDEF9C64256DEE61EBF5B212238DF11C7E532E3B7
someString: Hello World
someStringWithQuotes: '"Hello World"'

go的实际输出是不正确的,如果你使用Python输出字符串“0xDef9C64256DeE61ebf5B212238df11C7E532e3B7”,那么你会看到它输出 带引号的字符串(我在这里使用 ruamel.yaml,但这对于 PyYAML 来说是一样的):

import sys
import ruamel.yaml

data = dict(someHexValue="0xDef9C64256DeE61ebf5B212238df11C7E532e3B7")

yaml = ruamel.yaml.YAML()
yaml.dump(data, sys.stdout)

给出:

someHexValue: '0xDef9C64256DeE61ebf5B212238df11C7E532e3B7'

该字符串需要引用,是通过表示 字符串“plain”(即不带引号),然后尝试解决它 确保返回原始类型(字符串)。这不是 情况,因为它被发现是一个整数并且代表部分 倾销过程决定报价是必要的。 (如果你曾经看过 在加载和转储代码时,想知道为什么使用解析器 两者:这就是转储程序需要访问 resolver.py 的原因 好吧)。

这对于像 "True" 和 "2019-02-08' 这样的字符串也有同样的作用,它们也会被引用(按顺序) 不要将它们与 bool 值或日期“混淆”)。

这是一个相当昂贵的计算过程,当然还有其他方法 确定是否需要报价。

在go中,也是同样的原理,但是resolve.go中相关代码有错误:

        intv, err := strconv.ParseInt(plain, 0, 64)
        if err == nil {
            if intv == int64(int(intv)) {
                return yaml_INT_TAG, int(intv)
            } else {
                return yaml_INT_TAG, intv
            }
        }

来自 ParseInt 的文档:

If base == 0, the base is implied by the string's prefix: base 16 for "0x", base 8 for "0", and base 10 otherwise.

问题当然是 YAML 和 Python 关于整数的大小。但在 Go 中限制为 64 位。所以在上面的 ParseInt 返回一个错误并且 go 认为 字符串不需要引号。 (我将此报告为 bug在 go-yaml 中 库)。

出发 Marshall 函数似乎没有像您一样强制引用的标志 在 ruamel.yaml`` 中设置 yaml.default_style = '"'` 即可。

关于python - 如何使用 Go 和 Python 处理 YAML 中的十六进制值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54584832/

相关文章:

python - pwd.getpwnam(username).pw_dir 在 Windows 中的等价物是什么?

python - 如何通过jira-python获取默认组件

Golang - 解析 yaml 文件和检查对象的单元测试

json - 如何在 bash 中将 json 响应转换为 yaml

python - 根据未涵盖所有可能组合的数据创建计数表,并且 pandas 数据框中提供缺失值

python - 组的 AzCosmosDBSqlRoleAssignment 问题

xml - 如何从XML字符串中删除XML意向?

postgresql - golang Gorp Postgres 选择只返回一行

go - 从服务器端语言设置为 localStorage

html - 网站页脚中的四开安装版本