powershell-yamlでYAMLファイルを読み込む

# 概要

[powershell-yaml](https://github.com/cloudbase/powershell-yaml)でYAMLファイルを読み込むときは、`Get-Content`で読込んだ内容を改行コードで連結して文字列変数にしてから `ConvertFrom-YAML` する。

```powershell
PS> $yaml = (Get-Content "MyTemplate.yaml") -join "`n"
PS> ConvertFrom-YAML $yaml
```

あるいは `Get-Content` 時に区切り文字にnull文字を指定することで1つの文字列として丸読みして、`ConvertFrom-YAML` する。

```powershell
PS> $yaml = Get-Content "MyTemplate.yaml" -Delimiter "`0"
PS> ConvertFrom-YAML $yaml
```

# 詳細

## 問題

以下のように `ConvertTo-YAML` で生成（シリアライズ）した文字列を `ConvertFrom-YAML` で戻す（デシリアライズ）のは問題ない（勝手に型変換されてるのが問題なくもないけど）。

```powershell
PS> $data = [ordered]@{"AWSTemplateFormatVersion"="2010-09-09";"Description"="MyTemplate.yaml"}
PS> $yaml = ConvertTo-Yaml $data
PS> $yaml
AWSTemplateFormatVersion: 2010-09-09
Description: MyTemplate.yaml

PS> ConvertFrom-Yaml $yaml
Name                           Value
----                           -----
AWSTemplateFormatVersion       2010/09/09 0:00:00
Description                    MyTemplate.yaml
```

このYAML文字列を `Out-File` （リダイレクトでもいい）でファイルに出力し、 `Get-Content` でファイルから読込んでから `ConvertFrom-YAML` で戻そうとすると、エラーになる。

```powershell
PS> $yaml | Out-File "MyTemplate.yaml"
PS> Get-Content "MyTemplate.yaml"
AWSTemplateFormatVersion: 2010-09-09
Description: MyTemplate.yaml

PS> ConvertFrom-Yaml (Get-Content "MyTemplate.yaml")
ConvertFrom-Yaml: Cannot process argument transformation on parameter 'Yaml'. Cannot convert value to type System.String.
```

## 原因と回避方法

`ConvertFrom-Yaml` は変換対象に文字列をとるようになっている。`ConvertTo-Yaml` の出力は文字列型なので、これをそのまま渡す分には問題ない。

```powershell
PS> $data = [ordered]@{"AWSTemplateFormatVersion"="2010-09-09";"Description"="MyTemplate.yaml"}
PS> $yaml = ConvertTo-Yaml $data
PS> $yaml.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object
```

しかしファイル出力後に `Get-Content` で読込むと、一見元通りのYAML文字列が戻ってきているようだけれど、 `Get-Content` が1行1件の配列で読込結果を返している。

```powershell
PS> $yaml | Out-File "MyTemplate.yaml"
PS> $yaml = Get-Content "MyTemplate.yaml"
PS> $yaml
AWSTemplateFormatVersion: 2010-09-09
Description: MyTemplate.yaml
PS> $yaml.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
```

普通の配列なので、改行文字でで連結すれば1つの文字列変数になり、`ConvertFrom-Yaml` でも戻せるようになる。

```powershell
PS> $yaml = $yaml -join "`n"
PS> $yaml
AWSTemplateFormatVersion: 2010-09-09
Description: MyTemplate.yaml

PS> $yaml.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS> ConvertFrom-Yaml $yaml

Name                           Value
----                           -----
AWSTemplateFormatVersion       2010/09/09 0:00:00
Description                    MyTemplate.yaml
```

## より簡潔に書くために

もちろん読込んだ時点で改行文字で連結してしまってもいい。

```powershell
PS> $yaml = (Get-Content "MyTemplate.yaml") -join "`n"
PS> $yaml.GetType().Name
String
```

`Get-Content` の区切り文字にnullを指定してしまってもいい。

```powershell
PS> $yaml = Get-Content "MyTemplate.yaml" -Delimiter "`0"
PS> $yaml.GetType().Name
String
PS> ConvertFrom-Yaml $yaml

Name                           Value
----                           -----
AWSTemplateFormatVersion       2010/09/09 0:00:00
Description                    MyTemplate.yaml
```

ファイルを丸読みするために区切り文字にnull文字を指定するというのは、Perlなどで使ったテクニックだけど、PowerShellでもこれでうまくいった。本来の目的がファイルを丸読みすることなのでこれが一番きれいで、ワンライナーにもまとめやすい。

```powershell
PS> ConvertFrom-Yaml (Get-Content "MyTemplate.yaml" -Delimiter "`0")

Name                           Value
----                           -----
AWSTemplateFormatVersion       2010/09/09 0:00:00
Description                    MyTemplate.yaml
```

ただ個人的には、コーディング中にとっさに[null文字のエスケープシーケンス](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_special_characters?view=powershell-7.1#null-0)を思い出せる自信がない。

# 参考

* [PowerShellでYAMLを扱う - Qiita](https://qiita.com/tsukamoto/items/a3be3570bbc98f7f58ac)
* [powershell-yaml](https://github.com/cloudbase/powershell-yaml)
* [特殊文字について - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_special_characters?view=powershell-7.1#null-0)