問題

私はこの単純な次のプログラムを持っています:

 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))
 

Hex値を整数として解析します。このコードを使用して 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"'
 

Hex形式が保存されていることを確認するにはどうすればよいですか?残念ながら、私は個人的にGo側のコードに影響を与えません(しかし、Go-sideソリューションは、同様のことをしようとする他の人にとってはまだ歓迎しています)。

  ベストアンサー

ruamel.yamlを使用して16進値を保持しながら、Pythonで出力をロードしてダンプできます(免責事項:私はその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"'
 

Pythonを使用して文字列"0xDef9C64256DeE61ebf5B212238df11C7E532e3B7"を出力する場合、goの実際の出力は正しくありません。 引用符付きの文字列(私はここでruamel.yamlを使用していますが、これはPyYmainLでも同じです):

 import sys
import ruamel.yaml

data = dict(someHexValue="0xDef9C64256DeE61ebf5B212238df11C7E532e3B7")

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

それは与える:

 someHexValue: '0xDef9C64256DeE61ebf5B212238df11C7E532e3B7'
 

この文字列は、 文字列 "plain"(つまり引用符なし)を解決しようとしています 折りたたみ型(文字列)が返されるようにします。これは ケースは整数であり、 ダンププロセスは、引用符が必要であることを決定します。 ロードとダンプコードで、なぜリゾルバが使用されているのだろうか 両方とも:これは、dumperがresolver.pyにアクセスする必要がある理由です。 まあね)

これは、"True"や "2019-02-08"のような文字列と同じように動作します。これも引用符で囲まれます(順番に) それらをブール値または日付と "混同"しないでください)。

これはかなり高価な計算プロセスですが 引用符が必要かどうかを判断します。

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のドキュメントから:

base==0 の場合、ベースは文字列のプレフィックスによって暗示されます。

問題はもちろん、山Lや 整数のサイズのPython。しかし、行くには64に制限されています ビット。したがって、上記のparseIntはエラーを返し、 文字列は引用符を必要としません。 (私はこれを go-yamlのバグ ライブラリ)。

go Marshall 関数はあなたのような引用を強制するフラグを持っていないようです yaml.default_style = '"'` in ruamel.yamlを設定してください。

  同じタグがついた質問を見る

pythongoyaml