前置き
PowershellのInvoke-RestMethodコマンドレットでは、たまに日本語の文字化けが発生します。これはInboke-Restmethodが文字コードを誤って認識するために発生します。
戻り値の文字コードを指定する方法がないため、追加の対策にて文字コードを強制しましょう。
元ネタは以下です。
http://pierre3.hatenablog.com/entry/2014/12/13/001743
変換方法
まずはさらっとコードのご紹介です。
# NDLサーチからドラえもんの情報を拾う
$SearchData = 'title="ドラえもん" AND from="2017"'
$BaseUri = "http://iss.ndl.go.jp/api/sru?maximumRecords=10&operation=searchRetrieve&query="
Add-Type -AssemblyName System.Web
$OptionUri = [System.Web.HttpUtility]::UrlEncode($SearchData)
$uri = $BaseUri+ $OptionUri
# $xml = Invoke-RestMethod $uri
$res = Invoke-WebRequest $uri
$con =[System.Text.Encoding]::Utf8.GetString($res.RawContentStream.GetBuffer())
[xml]$xml = $con -replace "\u0000",""
$xml.searchRetrieveResponse.records.record[0].recordData
# REST APIの返却がJson形式の場合には以下を使用する。
$json = ConvertFrom-Json $con -replace "\u0000",""
まず、$resより前はリクエストのための情報なので、タイトルとは余り関係のない話ですが一応ご紹介です。
国会図書館サーチというサービスのSRUという検索APIを使用してタイトルに「ドラえもん」が含まれる蔵書(音楽CDなども含む)を検索し、結果をXMLで返しています。
このクエリー自体は実は化けないんですが、蔵書に海外の図書とかが含まれているからでしょうか、検索結果が化けたり化けなかったりするんです。
全部化ける前提のコードにすると化けなかった時に誤ったエンコード指定となってしまいます。
そこで、コマンドレットの自動変換に頼らず、一律でrawcontentからUTF8で読み込んでしまおうという訳です。
ただ、そうすると、パケットの詰め物なのかNUL(文字コード0000)が後方に埋まっているので文字列置換で取り除いてからXMLに変換しております。
補足
先日のElasticsearchの場合はElasticsearch側が仕様に反してましたが、今回はMS側が仕様に反している(一応)ので、そのうちこの回避策を使わなくてもPowershell側で対応してくれる可能性があります。
具体的には、JSONはRFC 8259にてエンコーディングにUTF-8を使用することを要件とされているため、Content-Typeの判定がJSONだった時点で、エンコーディングにISO-8859-1を利用してしまうのは仕様に反しております。
上の例はXMLなのでその制限はありません。ただ、これもコンテンツにencoding指定があるのでそれを元にUTF8で変換されるべきでしょうね。
0 件のコメント:
コメントを投稿