LoginSignup
18

More than 1 year has passed since last update.

PowerShellで HTTPアクセスする いくつかの方法

Last updated at Posted at 2021-04-25

PowerShellを使って手軽にHTTPアクセスしたいと思い、調べてみました。
手軽にできたのですが、色々やり方があり、少し整理したくなったので、まとめてみました。

HTTPクライアント

HTTPアクセスするためのクライアント機能は、Invoke-WebRequestコマンドレット、Invoke-RestMethodコマンドレットとして提供されていました。
ただし、PowerShell 3.0 以降です。
古い環境では、これらのコマンドレットが使えないので、替わりに .NET Framework を使うことで、実現できました。

主要コマンドレット/クラス

  • Invoke-WebRequestコマンドレット:PowerShell 3.0 以降
  • Invoke-RestMethodコマンドレット:PowerShell 3.0 以降
  • HttpClientクラス:.NET Framework 4.5 以降(なので、PowerShell 4.0 以降。Invoke-WebRequest/Invoke-RestMethodコマンドレットで概ね同じことができると思ったので今回未使用。)
  • WebClientクラス:.NET Framework 1.1 以降(なので、どのPowerShellバージョンでも使用可能。HttpWebRequest/HttpWebResponseクラスより少し便利。)
  • HttpWebRequest/HttpWebResponseクラス:.NET Framework 1.1 以降(なので、どのPowerShellバージョンでも使用可能。WebClientクラスより細かいことができる。)

上記のように、HTTPアクセスするためのコマンドレットやクラスが色々用意されています。
正直、どれを使えばよいのか迷ってしまったのですが、一通り触ってみて、次のように使い分ければよいのかな、と思いました。

  • PowerShell 3.0 以降の環境
    • APIをコールするなら、Invoke-RestMethodコマンドレット
    • Webページを取得するなら、Invoke-WebRequestコマンドレット
  • PowerShell 2.0 以前の環境
    • 基本、WebClientクラス
    • リクエスト/レスポンスを細かく制御したいなら、HttpWebRequest/HttpWebResponseクラス

Invoke-WebRequestコマンドレット

GETメソッド

例:Google検索(GETメソッド、KeyValue風リクエスト、HTMLレスポンス)

$url = 'https://www.google.com/search'
$params = @{"q"="Powershell"}

# 方式1.コンテンツをレスポンスオブジェクトとして取得
$res = Invoke-WebRequest $url -Body $params

# 方式2.コンテンツをファイルに保存
Invoke-WebRequest $url -Body $params -OutFile 'D:\tmp\out.txt'

# 補足.エラー考慮
try {
  $res = Invoke-WebRequest 'https://www.google.com/存在しないページ'
  $res.StatusCode.ToString() + " " + $res.StatusDescription 
  $res.Headers
  $res.Content
} catch {
  # ステータスコード
  echo $_.Exception.Response.StatusCode.value__
  # レスポンスボディ
  $stream = $_.Exception.Response.GetResponseStream()
  $reader = New-Object System.IO.StreamReader $stream
  $reader.BaseStream.Position = 0
  $reader.DiscardBufferedData()
  echo $reader.ReadToEnd()
  $reader.Close()  # Closeは$readerと$streamの一方を呼び出せばよい。両方呼び出しても害はない
  $stream.Close()
}

# 補足.レスポンスHTMLを解析
$res = Invoke-WebRequest 'https://weather.yahoo.co.jp/weather/jp/13/4410.html'
$res.ParsedHtml.title
$res.ParsedHtml.getElementById("wrnrpt").innerText
$res.ParsedHtml.getElementsByName("description") | %{ $_.GetAttribute("content") }
$res.ParsedHtml.getElementsByTagName("title") | %{ $_.innerText }
  • Invoke-WebRequestに、-SessionVariableパラメータを設定するとセッション情報を変数に保存できて、次のInvoke-WebRequest実行時に、-WebSessionパラメータを設定してセッション情報を引き継いだアクセスができるらしい。

例:Yahoo! JAPAN 日本語形態素解析WebAPI(GETメソッド、KeyValue風リクエスト、XMLレスポンス)

$clientid = "あなたの Yahoo! JAPAN WebAPI 用クライアントID を設定する"
$url = "https://jlp.yahooapis.jp/MAService/V1/parse"
$params = @{
  "appid" = $clientid;
  "results" = "ma,uniq";
  "uniq_filter" = "9|10";
  "sentence" = "庭には二羽ニワトリがいる。"}
$res = Invoke-WebRequest $url -Body $params
$xmlobj = [Xml]$res.Content
$xmlobj.OuterXml

POSTメソッド

例:Yahoo! JAPAN 日本語形態素解析WebAPI(POSTメソッド、KeyValue風リクエスト、XMLレスポンス)

$url = "https://jlp.yahooapis.jp/MAService/V1/parse" 
$headers = @{
  "User-Agent" = "Yahoo AppID: $clientid";
  "Content-Type" = "application/x-www-form-urlencoded"}

# 方式1.POSTデータを文字列で指定。
$poststr = "results=ma,uniq" +
  "&uniq_filter=" + [System.Web.HttpUtility]::UrlEncode("9|10") +
  "&sentence=" + [System.Web.HttpUtility]::UrlEncode("庭には二羽ニワトリがいる。")
$res = Invoke-WebRequest $url -Method 'POST' -Headers $headers -Body $poststr
$xmlobj = [Xml]$res.Content
$xmlobj.OuterXml

# 方式2.POSTデータを連想配列で指定。自動でURLエンコードされる。
$params = @{
  "results" = "ma,uniq"; 
  "uniq_filter" = "9|10"; 
  "sentence" = "庭には二羽ニワトリがいる。"}
$res = Invoke-WebRequest $url -Method 'POST' -Headers $headers -Body $params
$xmlobj = [Xml]$res.Content
$xmlobj.OuterXml

例:日本語係り受け解析(POSTメソッド、JSONリクエスト/レスポンス)

$url = 'https://jlp.yahooapis.jp/DAService/V2/parse'
$headers = @{
  "User-Agent" = "Yahoo AppID: $clientid";
  "Content-Type" = "application/x-www-form-urlencoded"}
# JSONリクエスト。もしASCII文字だけならエンコード不要。
$poststr = ConvertTo-Json @{
  id="123"; jsonrpc="2.0"; method="jlp.daservice.parse";
  params=@{q="うちの庭には二羽鶏がいます"}}
$postbytes = [System.Text.Encoding]::UTF8.GetBytes($poststr)
$res = Invoke-WebRequest $url -Method 'POST' -Headers $headers -Body $postbytes
$jsonobj = ConvertFrom-Json $res.Content
Write-Output (ConvertTo-Json $jsonobj -Depth 100)

Invoke-RestMethodコマンドレット

GETメソッド

例:Yahoo! JAPAN 日本語形態素解析WebAPI(GET)

$clientid = "あなたの Yahoo! JAPAN WebAPI 用クライアントID を設定する"
$url = "https://jlp.yahooapis.jp/MAService/V1/parse"
$params = @{
  "appid" = $clientid;
  "results" = "ma,uniq";
  "uniq_filter" = "9|10";
  "sentence" = "庭には二羽ニワトリがいる。"}
$xmldoc = Invoke-RestMethod $url -Body $params
Write-Output $xmldoc.OuterXml

# エラーを考慮する場合
try {
  $xmldoc = Invoke-RestMethod "https://jlp.yahooapis.jp/存在しないページ" -Body $params
  Write-Output $xmldoc.OuterXml
} catch {
  # ステータスコード
  echo $_.Exception.Response.StatusCode.value__
  # レスポンスボディ
  $stream = $_.Exception.Response.GetResponseStream()
  $reader = New-Object System.IO.StreamReader $stream
  $reader.BaseStream.Position = 0
  $reader.DiscardBufferedData()
  echo $reader.ReadToEnd()
  $reader.Close()  # Closeは$readerと$streamの一方を呼び出せばよい。両方呼び出しても害はない
  $stream.Close()
}

POSTメソッド

例:Yahoo! JAPAN 日本語形態素解析WebAPI(POST)

$url = "https://jlp.yahooapis.jp/MAService/V1/parse" 
$headers = @{
  "User-Agent" = "Yahoo AppID: $clientid";
  "Content-Type" = "application/x-www-form-urlencoded"}

# 方式1.POSTデータを文字列で指定。
$poststr = "results=ma,uniq" +
  "&uniq_filter=" + [System.Web.HttpUtility]::UrlEncode("9|10") +
  "&sentence=" + [System.Web.HttpUtility]::UrlEncode("庭には二羽ニワトリがいる。")
$xmldoc = Invoke-RestMethod $url -Method 'POST' -Headers $headers -Body $poststr
Write-Output $xmldoc.OuterXml

# 方式2.POSTデータを連想配列で指定。自動でURLエンコードされる。
$params = @{
  "results" = "ma,uniq"; 
  "uniq_filter" = "9|10"; 
  "sentence" = "庭には二羽ニワトリがいる。"}
$xmldoc = Invoke-RestMethod $url -Method 'POST' -Headers $headers -Body $params
Write-Output $xmldoc.OuterXml

例:日本語係り受け解析(POSTメソッド、JSONリクエスト)

$url = 'https://jlp.yahooapis.jp/DAService/V2/parse'
$headers = @{
  "User-Agent" = "Yahoo AppID: $clientid";
  "Content-Type" = "application/x-www-form-urlencoded"}

# JSONリクエスト。もしASCII文字だけならエンコード不要。
$poststr = ConvertTo-Json @{
  id="123"; jsonrpc="2.0"; method="jlp.daservice.parse";
  params=@{q="うちの庭には二羽鶏がいます"}}
$postbytes = [System.Text.Encoding]::UTF8.GetBytes($poststr)
$res = Invoke-RestMethod $url -Method 'POST' -Headers $headers -Body $postbytes
Write-Output (ConvertTo-Json $res -Depth 100)

WebClientクラス

GETメソッド

例:Google検索(GETメソッド)

$url = 'https://www.google.com/search'
$wc = New-Object System.Net.WebClient 
$wc.QueryString.Add("q", "Powershell")

# 方式1.コンテンツを取得し保存。テキストのエンコード変換なしの模様。 
$wc.DownloadFile($url, 'D:\tmp\out.txt')

# 方式2.コンテンツをバイト配列として取得 
$resbytes = $wc.DownloadData($url) 

# 方式3.コンテンツを文字列として取得。必要なら$wc.Encodingにエンコードを指定する。 
$resstr = $wc.DownloadString($url)

# エラーを考慮する場合
try {
  $resstr = $wc.DownloadString('https://www.google.com/存在しないページ')
} catch {
  # ステータスコード
  echo $_.Exception.InnerException.Response.StatusCode.value__
  # レスポンスボディ
  $stream = $_.Exception.InnerException.Response.GetResponseStream()
  $reader = New-Object System.IO.StreamReader $stream
  $reader.BaseStream.Position = 0
  $reader.DiscardBufferedData()
  echo $reader.ReadToEnd()
  $reader.Close()  # Closeは$readerと$streamの一方を呼び出せばよい。両方呼び出しても害はない
  $stream.Close()
}

# 後片付け
$wc.Dispose()

例:Yahoo! JAPAN 日本語形態素解析WebAPI(GET)

$clientid = "あなたの Yahoo! JAPAN WebAPI 用クライアントID を設定する"
$url = "https://jlp.yahooapis.jp/MAService/V1/parse"
$wc = New-Object System.Net.WebClient
$wc.Encoding = [System.Text.Encoding]::UTF8
$wc.QueryString.Add("appid", $clientid)
$wc.QueryString.Add("results", "ma,uniq")
$wc.QueryString.Add("uniq_filter", "9|10")
$wc.QueryString.Add("sentence", "庭には二羽ニワトリがいる。")
$resstr = $wc.DownloadString($url)
$wc.Dispose()
Write-Output $resstr

POSTメソッド

例:Yahoo! JAPAN 日本語形態素解析WebAPI(POST)

Add-Type -AssemblyName System.Web
$url = "https://jlp.yahooapis.jp/MAService/V1/parse"
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("User-Agent", "Yahoo AppID: $clientid")
$wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
$wc.Encoding = [System.Text.Encoding]::UTF8

# 方式1.POSTデータを文字列で設定
$poststr = "results=ma,uniq" +  
  "&uniq_filter=" + [System.Web.HttpUtility]::UrlEncode("9|10") + 
  "&sentence=" + [System.Web.HttpUtility]::UrlEncode("庭には二羽ニワトリがいる。")
$resstr = $wc.UploadString($url, $poststr) 
Write-Output $resstr

# 方式2.POSTデータを名前と値のコレクションで設定
$posthash = New-Object System.Collections.Specialized.NameValueCollection 
$posthash.Add("results", "ma,uniq") 
$posthash.Add("uniq_filter", "9|10") 
$posthash.Add("sentence", "庭には二羽ニワトリがいる。") 
$resbytes = $wc.UploadValues($url, $posthash) 
$resstr = [System.Text.Encoding]::UTF8.GetString($resbytes)
Write-Output $resstr

# 方式3.POSTデータをバイト配列で設定(byte[] UploadData(string url, byte[] postdata))
# →省略

# 後片付け
$wc.Dispose() 

例:日本語係り受け解析(POSTメソッド、JSONリクエスト/レスポンス)

Add-Type -AssemblyName System.Web
$url = 'https://jlp.yahooapis.jp/DAService/V2/parse'
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("User-Agent", "Yahoo AppID: $clientid")
$wc.Headers.Add("Content-Type", "application/json")
$wc.Encoding = [System.Text.Encoding]::UTF8
# JSONリクエスト。もしASCII文字だけなら$wc.UploadString()を使用可能。
$poststr = '{"id":"123","jsonrpc":"2.0","method":"jlp.daservice.parse","params":{' +
  '"q":"うちの庭には二羽鶏がいます"' +
  '}}'
$postbytes = [System.Text.Encoding]::UTF8.GetBytes($poststr)
$resbytes = $wc.UploadData($url, $postbytes)
$resstr = [System.Text.Encoding]::UTF8.GetString($resbytes)
Write-Output $resstr
# 後片付け
$wc.Dispose()

HttpWebRequest/HttpWebResponseクラス

  • HTTPリクエスト時のヘッダー情報は、HttpWebRequest のプロパティとして設定可能。(例:$res.UserAgent = xxx)
  • プロパティで用意されていないヘッダー情報は、HttpWebRequest の Headers プロパティに設定する。(例:$res.Headers['Authorization'] = xxx)

GETメソッド

例:Google検索(GETメソッド)

$url = 'https://www.google.com/search?q=Powershell'
$req = [System.Net.WebRequest]::Create($url)
$res = $req.GetResponse()
echo ($res.StatusCode.value__.ToString() + " " + $res.StatusDescription)
$stream = $res.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::UTF8)
echo $reader.ReadToEnd()
$res.Close()  # $stream.Close(),$reader.Close()でも良いし、3つとも実行しても良い。

# エラーを考慮する場合
try {
  $url = 'https://www.google.com/存在しないページ'
  $req = [System.Net.WebRequest]::Create($url)
  $res = $req.GetResponse()
  echo ($res.StatusCode.value__.ToString() + " " + $res.StatusDescription)
  $stream = $res.GetResponseStream()
  $reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::UTF8)
  echo $reader.ReadToEnd()
  $res.Close()
} catch {
  # ステータスコード
  echo $_.Exception.InnerException.Response.StatusCode.value__
  # レスポンスボディ
  $stream = $_.Exception.InnerException.Response.GetResponseStream()
  $reader = New-Object System.IO.StreamReader $stream
  $reader.BaseStream.Position = 0
  $reader.DiscardBufferedData()
  echo $reader.ReadToEnd()
  $stream.Close()  # $reader.Close()でも良いし、2つとも実行しても良い。
}

例:Yahoo! JAPAN 日本語形態素解析WebAPI(GETメソッド)

$clientid = "あなたの Yahoo! JAPAN WebAPI 用クライアントID を設定する"
$url = "https://jlp.yahooapis.jp/MAService/V1/parse" +
  "?appid=" + $clientid +
  "&results=ma,uniq" +
  "&uniq_filter=9|10" +
  "&sentence=庭には二羽ニワトリがいる。"
$url = [Uri]::EscapeUriString($url)
$req = [System.Net.WebRequest]::Create($url)
$res = $req.GetResponse()
echo ($res.StatusCode.value__.ToString() + " " + $res.StatusDescription)
$stream = $res.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::UTF8)
echo $reader.ReadToEnd()
$res.Close()

POSTメソッド

例:Yahoo! JAPAN 日本語形態素解析WebAPI(POSTメソッド、KeyValue風リクエスト)

# データ準備
Add-Type -AssemblyName System.Web
$url = "https://jlp.yahooapis.jp/MAService/V1/parse"
$postStr = "results=ma,uniq" +  
  "&uniq_filter=" + [System.Web.HttpUtility]::UrlEncode("9|10") + 
  "&sentence=" + [System.Web.HttpUtility]::UrlEncode("庭には二羽ニワトリがいる。")
$postBytes = [System.Text.Encoding]::UTF8.GetBytes($postStr)
# リクエスト送信
$req = [System.Net.WebRequest]::Create($url)
$req.Method = "POST"
$req.UserAgent = "Yahoo AppID: $clientid"
$req.ContentType = "application/x-www-form-urlencoded"
$req.ContentLength = $postBytes.Length
$stream = $req.GetRequestStream()
$stream.Write($postBytes, 0, $postBytes.Length)
$stream.Close()
# レスポンス受信
$res = $req.GetResponse()
echo ($res.StatusCode.value__.ToString() + " " + $res.StatusDescription)
$stream = $res.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::UTF8)
echo $reader.ReadToEnd()
$res.Close()

例:日本語係り受け解析(POSTメソッド、JSONリクエスト)

Add-Type -AssemblyName System.Web
$url = 'https://jlp.yahooapis.jp/DAService/V2/parse'
$postStr = '{"id":"123","jsonrpc":"2.0","method":"jlp.daservice.parse","params":{' +
  '"q":"うちの庭には二羽鶏がいます"' +
  '}}'
$postBytes = [System.Text.Encoding]::UTF8.GetBytes($postStr)
# リクエスト送信
$req = [System.Net.WebRequest]::Create($url)
$req.Method = "POST"
$req.UserAgent = "Yahoo AppID: $clientid"
$req.ContentType = "application/json"
$req.ContentLength = $postBytes.Length
$stream = $req.GetRequestStream()
$stream.Write($postBytes, 0, $postBytes.Length)
$stream.Close()
# レスポンス受信
$res = $req.GetResponse()
echo ($res.StatusCode.value__.ToString() + " " + $res.StatusDescription)
$stream = $res.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::UTF8)
echo $reader.ReadToEnd()
$res.Close()

エンコーディング

HTTPアクセスするときに必要となるエンコーディングについて、メモしておきます。

テキストのエンコーディング

.NET Framwork の Encodingクラスを使用して、テキストのエンコーディングを変更することができました。

$enc = [System.Text.Encoding]::UTF8
$enc = [System.Text.Encoding]::GetEncoding("SJIS")
# 指定したエンコーディングに変換した文字列のバイト配列を取得
$bytes = $enc.GetBytes("日本語テキストです")
# バイト配列を指定したエンコーディングとして解釈して文字列を取得
$str = $enc.GetString($bytes)

パーセントエンコーディング

次の2種類がある。

  • パーセントエンコーディングによる符号化 : URLのパス部分を符号化する方式。半角スペースが「%20」となる。RFC3986。
  • application/x-www-form-urlencodedによる符号化 : HTTPのPOSTメソッドで送信する文字列に対する符号化方式。半角スペースが「+」となる。

パーセントエンコーディングによる符号化は、.NET Framework の Uriクラスを使用して、実現できました。

  • .NET Framework 2.0 以降(PowerShell 2.0 以降)
  • .NET Framework 4.0以前と4.5以降で、エンコード対象の記号が少し異なる。
$url = 'https://www.google.com/search?q=Powershell 日本語'
# 文字列全体をエンコード
$encstr = [Uri]::EscapeDataString($url)      #=> "https%3A%2F%2Fwww.google.com%2Fsearch%3Fq%3DPowershell%20%E6%97%A5%E6%9C%AC%E8%AA%9E"
$decstr = [Uri]::UnescapeDataString($encstr)
# 予約文字以外をエンコード
$encstr = [Uri]::EscapeUriString($url)       #=> "https://www.google.com/search?q=Powershell%20%E6%97%A5%E6%9C%AC%E8%AA%9E"
$decstr = [Uri]::UnescapeDataString($encstr)

application/x-www-form-urlencodedによる符号化は、.NET Framework の HttpUtilityクラスを使用して、実現できました。

  • .NET Framework 1.1 以降(PowerShell 1.0 以降)
Add-Type -AssemblyName System.Web
$str = "POSTデータ abc :/?&=<>"
# エンコード。デフォルトでUTF8を使用。必要なら第2引数にEncodingを指定する。
$encstr = [System.Web.HttpUtility]::UrlEncode($str)  #=> "POST%e3%83%87%e3%83%bc%e3%82%bf+abc+%3a%2f%3f%26%3d%3c%3e"
# デコード。デフォルトでUTF8を使用。必要なら第2引数にEncodingを指定する。
$decstr = [System.Web.HttpUtility]::UrlDecode($encstr)

コンテンツのデータ形式

HTTPレスポンスで受信するコンテンツのデータ形式について、メモしておきます。
JSONはリクエスト時にも使用する場合あり。
もしかすると、XMLでリクエストすることもあり得るかも。

HTML

ConvertTo-Htmlコマンドレット

COMを使用して、HTMLをパースする方法です。

$sample = "<html><head><title>サンプル</title></head>" +
  "<body><span id='text1' name='text1'>サンプルページです。</span></body></html>"
$html = New-Object -com "HTMLFILE"
$html.IHTMLDocument2_write($sample)
$html.Close()
echo $html.title
echo $html.getElementById("text1").innerText
$html.getElementsByName("text1") | %{ echo $_.innerText }
$html.getElementsByTagName("span") | %{ echo $_.innerText }

XML

.NET Framework の XmlDocumentクラスを使用して、XMLの解析や組み立てを行ってみました。

# XMLオブジェクトの作成
$doc = New-Object System.Xml.XmlDocument
$doc.AppendChild($doc.CreateXmlDeclaration("1.0", "utf-8", $null)) | Out-Null
$root = $doc.AppendChild($doc.CreateElement("Root"))
$item1 = $root.AppendChild($doc.CreateElement("Item1"))
$item1.AppendChild($doc.CreateTextNode("text")) | Out-Null
# 文字列表現
Write-Output $doc.OuterXml
# ファイルに保存(BOM付きUTF8)
$doc.Save('D:\tmp\tmp.xml')

# XML文字列の読み込み
$doc = [Xml]'<?xml version="1.0" encoding="utf-8"?><Root><Item1>text</Item1></Root>'
$doc = [System.Xml.XmlDocument]'<?xml version="1.0" encoding="utf-8"?><Root><Item1>text</Item1></Root>'
Write-Output $doc.Root.Item1 

# XMLファイルから読み込み 
$doc = New-Object System.Xml.XmlDocument 
$doc.Load('D:\tmp\tmp.xml') 
Write-Output $doc.Root.Item1

JSON

ConvertFrom-Jsonコマンドレット、ConvertTo-Jsonコマンドレットを利用しました。

# オブジェクトをJSON文字列に変換。Depthの最大値は100
$jsonstr = ConvertTo-Json -Depth 100 @{
  Number = 123;
  String = '日本語 記号''"{}<>';
  DateTimeStr = Get-Date -Format "yyyy/MM/dd HH:mm:ss";
  Array = @(1,2,3);
  Hash = @{Key1="value1"; Key2="value2"};
  Null = $null;
}
# JSON文字列をオブジェクトに変換
$jsonobj = ConvertFrom-Json '{"Number":123, "String":"日本語 記号''\"{}<>", "DateTimeStr":"2021/1/1 01:02:03", "Array":[1,2,3], "Hash":{"Key1":"value1", "Key2":"value2"}, "Null":null}'

上記だと、PowerShell 3.0 以降でないと動作しないので、古い環境でも動作するように、簡易的な関数を考えてみました。
ただし、ハッシュデータをJSON文字列に変換する関数のみ。その逆の変換は、手間がかかりそうなので割愛。

function ConvertToJson($data) {
  if ($data -is [string]) {
    '"' + $data + '"'
  } elseif ($data -is [Array]) {
    $arr = $data | %{
      ConvertToJson $_
    }
    '[' + ($arr -join ', ') + ']'
  } elseif ($data -is [Hashtable]) {
    $arr = $data.GetEnumerator() | sort Key | %{
      '"' + $_.Key + '": ' + (ConvertToJson $_.Value)
    }
    '{' + ($arr -join ', ') + '}'
  } else {
    $data
  }
}
$hash = @{
  Number = 123;
  String = "abc";
  Array = @(1,2,3,@(4,5));
  Hash = @{Key1="value1"; Key2="value2"};
}
$jsonstr = ConvertToJson $hash

補足

動作確認環境

  • Windows 10
  • PowerShell 5.1

参考にしたサイト

Invoke-WebRequest/Invoke-WebRequestコマンドレット

WebClient/HttpWebRequest/HttpWebResponseクラス

その他

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18