注意: Ruby V3.1では非互換
YAMLにアンカー、エイリアスがあるとエラーとなります。
その場合、YAML.loadであればYAML.unsafe_loadに置き換えてください。
コマンドラインから Ruby | Python | jq を用いた JSON <-> YAML の変換、および JSON, YAML, XML の整形の例 を示す。
環境
$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin15]
$ python --version
Python 3.8.2
$ jq --version
jq-1.6
MAC OS 10.13.6 に Chef Development Kit Version: 3.3.23 を導入し echo 'eval "$(chef shell-init bash)"' >> ~/.bash_profile としている環境
jqとその前提であるyqの導入方法例
環境 Fedora 32 (Workstation Edition)
$ sudo yum install jq
...
$ pip3 install --user yq
...
#JSON -> YAML の変換
Ruby による JSON -> YAML の変換
- ruby -r json -r yaml -e "puts YAML.dump_stream(JSON.parse(STDIN.read))"
$ echo '{ "foo": { "bar":0, "baz":1 }, "qux": { "quux":2, "corge":3 } }' | \
ruby -r json -r yaml -e "puts YAML.dump_stream(JSON.parse(STDIN.read))"
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
Python による JSON -> YAML の変換
- python -c "import yaml; import json; import sys; print(yaml.dump(json.load(sys.stdin)))"
$ echo '{ "foo": { "bar":0, "baz":1 }, "qux": { "quux":2, "corge":3 } }' | python -c "import yaml; import json; import sys; print(yaml.dump(json.load(sys.stdin)))"
foo:
bar: 0
baz: 1
qux:
corge: 3
quux: 2
Python 3.8.2では問題なかったのですが、Python 3.6.2ではimport yamlが以下のエラーで失敗。
ModuleNotFoundError: No module named 'yaml'
PyYAMLモジュールが必要なのかもしれません。
https://pcl.solima.net/pyblog/archives/567
https://qiita.com/sot528/items/dc401a2d9676f9cda01f
yq -y . による JSON -> YAML の変換
$ echo '{ "foo": { "bar":0, "baz":1 }, "qux": { "quux":2, "corge":3 } }' | yq -y .
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
YAML -> JSON の変換
Ruby による YAML -> JSON の変換
- ruby -r json -r yaml -e "puts JSON.pretty_generate(YAML.load(STDIN.read))"
$ echo "
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
" | ruby -r json -r yaml -e "puts JSON.pretty_generate(YAML.load(STDIN.read))"
{
"foo": {
"bar": 0,
"baz": 1
},
"qux": {
"quux": 2,
"corge": 3
}
}
Python による YAML -> JSON の変換
- python -c "import yaml; import json; import sys; print(json.dumps(yaml.load(sys.stdin, Loader=yaml.FullLoader), indent=2))"
$ echo "
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
" | python -c "import yaml; import json; import sys; print(json.dumps(yaml.load(sys.stdin, Loader=yaml.FullLoader), indent=2))"
{
"foo": {
"bar": 0,
"baz": 1
},
"qux": {
"quux": 2,
"corge": 3
}
}
上と同様にPythonのレベルによってはPyYAMLが必要となる可能性がある。
yq . による YAML -> JSON の変換
echo "
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
" | yq .
{
"foo": {
"bar": 0,
"baz": 1
},
"qux": {
"quux": 2,
"corge": 3
}
}
#JSONの整形
Ruby による JSON の整形
- ruby -r json -e "puts JSON.pretty_generate(JSON.parse(STDIN.read))"
$ echo '{ "foo": { "bar":0, "baz":1 }, "qux": { "quux":2, "corge":3 } }' | \
ruby -r json -e "puts JSON.pretty_generate(JSON.parse(STDIN.read))"
{
"foo": {
"bar": 0,
"baz": 1
},
"qux": {
"quux": 2,
"corge": 3
}
}
当初JSON.loadを使用していたが、{ "json_class": "Chef::Role" } にて失敗することがあった為、JSON.perseに置き換え
Python による JSON の整形
- python -c "import json; import sys; print(json.dumps(json.load(sys.stdin), indent=2))"
$ echo '{ "foo": { "bar":0, "baz":1 }, "qux": { "quux":2, "corge":3 } }' | \
python -c "import json; import sys; print(json.dumps(json.load(sys.stdin), indent=2))"
{
"foo": {
"bar": 0,
"baz": 1
},
"qux": {
"quux": 2,
"corge": 3
}
}
yq . による JSON の整形
$ echo '{ "foo": { "bar":0, "baz":1 }, "qux": { "quux":2, "corge":3 } }' | yq .
{
"foo": {
"bar": 0,
"baz": 1
},
"qux": {
"quux": 2,
"corge": 3
}
}
#YAMLの整形
Ruby による YAML の整形
- ruby -r yaml -e "puts YAML.dump_stream(YAML.load(STDIN.read))"
$ echo "
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
" | ruby -r yaml -e "puts YAML.dump_stream(YAML.load(STDIN.read))"
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
Python による YAML の整形
- python -c "import yaml; import sys; print(yaml.dump(yaml.load(sys.stdin, Loader=yaml.FullLoader)))"
$ echo "
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
" | python -c "import yaml; import sys; print(yaml.dump(yaml.load(sys.stdin, Loader=yaml.FullLoader)))"
foo:
bar: 0
baz: 1
qux:
corge: 3
quux: 2
上と同様にPythonのレベルによってはPyYAMLが必要となる可能性がある。
yq -y . による YAML の整形
$ echo "
---
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
" | yq -y .
foo:
bar: 0
baz: 1
qux:
quux: 2
corge: 3
YAML整形の相違
yq -y . | ruby | python | |
---|---|---|---|
directoryにおける順序 | 保たれる | 保たれる | 保たれない |
&id001, *id001などによる参照 | 展開される | &1などに変更 | &id001などに変更 |
インデント | あける傾向 | つめる傾向 | つめる傾向 |
YAMLフロースタイル | ブロックスタイルに展開 | ブロックスタイルに展開 | ブロックスタイルに展開 |
コメント | 削除 | 削除 | 削除 |
>によるヒアドキュメント | 行をまとめる | 行をまとめる | 行をまとめる |
縦線によるヒアドキュメント | 先頭行は縦棒を除いてつめ、全体を'で囲いその内部で改行を保つ | 書式は保たれる | 先頭行は縦棒を除いてつめ、全体を'で囲いその内部で改行を保つ |
文字列のvalueにおける前後の'や" | 削除 | 削除 | 削除 |
>によるvalueである文字列の内容が'文字で開始される場合 | 文字列全体を'で囲い、内部の'は''(シングルクォート2つ)に置き換え | 文字列全体を"(ダブルクォート)で囲い、内部の'はそのまま | 文字列全体を'で囲い、内部の'は''(シングルクォート2つ)に置き換え |
>によるvalueである文字列の内容が"文字で開始される場合 | 文字列全体を'で囲い、内部の"はそのまま | 文字列全体を"(ダブルクォート)で囲い、内部の"は"とエスケープ | 文字列全体を'で囲い、内部の"はそのまま |
インデントはオプションにより制御できるかもしれない
コメントを自動的に残すのは困難か。
#XMLの整形
- ruby -r nokogiri -e "puts Nokogiri::XML(STDIN.read, &:noblanks).to_xml"
$ echo '<?xml version="1.1" encoding="UTF-8"?> <foo> <bar>val</bar> </foo>' | \
ruby -r nokogiri -e "puts Nokogiri::XML(STDIN.read, &:noblanks).to_xml"
<?xml version="1.1" encoding="UTF-8"?>
<foo>
<bar>val</bar>
</foo>
#参考
YAML <-> JSON 変換 (Rubyで実装)
[Python] [Tips] ワンライナー(?)でyaml->json
JSONの整形をvim(jq)だけで手軽に済ませてみる