WordPress の API を .NET のプログラムでつついていたところ、記事の投稿操作を行った際に下記のエラーが発生。
すぐに気付けたけど沼る方もいそうだなと思ったため、念のための備忘録です。
StreamWriter 使って Stream に JSON を書いてる方に当てはまるかも。
WordPress から返ってきたエラーの内容↓
結論
.NET の StreamWriter を使う際は、BOM に気をつけよう
無効な JSON というので、どんな壊れた内容で API をコールしてしまったのかとデバッガを覗いたところ、
見た目上はきれいな JSON が渡されているようでした。
見た目上は。
問題は、リクエスト時に送信する JSON を StreamWriter を使って Stream に書いていた時に起こっていました。
まずシリアライズ ツールを使って生成した JSON を String 型の文字列に格納し、その後送信用の Stream に StreamWriter を使って書いていました。
こんな感じ
良くなかったのがここで StreamWriter の Encoding 指定に Encoding.UTF8 を使っていたこと。
書き込み先の Stream の頭に BOM が付与されてしまい、それで受け取った側の WordPress が壊れた JSON として認識したようです。
雑なサンプルコードですが、UTF8 を使いたい場合は Encoding.UTF8 を使わずに、UTF8Encoding を new して、コンストラクタの第一引数に false を与えてあげましょう。BOM が付与されなくなります。
まぁそもそも、使っているシリアライザが System.Text.Json 名前空間のものなのですが、
デバッガで見た内容からして、ASCII で送信可能な状態にエンコーディングしてくれているので、UTF8 を使う必要がないと言えば無いのですが、ちょっとデバッグ目的で使いたて……ですね…… (もごもご)
すぐに気付けたけど沼る方もいそうだなと思ったため、念のための備忘録です。
StreamWriter 使って Stream に JSON を書いてる方に当てはまるかも。
WordPress から返ってきたエラーの内容↓
rest_invalid_json: 無効な JSON ボディが渡されました。
結論
.NET の StreamWriter を使う際は、BOM に気をつけよう
無効な JSON というので、どんな壊れた内容で API をコールしてしまったのかとデバッガを覗いたところ、
見た目上はきれいな JSON が渡されているようでした。
見た目上は。
問題は、リクエスト時に送信する JSON を StreamWriter を使って Stream に書いていた時に起こっていました。
まずシリアライズ ツールを使って生成した JSON を String 型の文字列に格納し、その後送信用の Stream に StreamWriter を使って書いていました。
こんな感じ
var json = JsonSerializer.Serialize(obj, this._serializerOptions);
var ms = new MemoryStream();
using (var sw = new StreamWriter(ms, Encoding.UTF8, 512, true))
{
await sw.WriteAsync(json);
}
良くなかったのがここで StreamWriter の Encoding 指定に Encoding.UTF8 を使っていたこと。
書き込み先の Stream の頭に BOM が付与されてしまい、それで受け取った側の WordPress が壊れた JSON として認識したようです。
雑なサンプルコードですが、UTF8 を使いたい場合は Encoding.UTF8 を使わずに、UTF8Encoding を new して、コンストラクタの第一引数に false を与えてあげましょう。BOM が付与されなくなります。
var json = JsonSerializer.Serialize(obj, this._serializerOptions);
var ms = new MemoryStream();
using (var sw = new StreamWriter(ms, new UTF8Encoding(false), 512, true))
{
await sw.WriteAsync(json);
}
まぁそもそも、使っているシリアライザが System.Text.Json 名前空間のものなのですが、
デバッガで見た内容からして、ASCII で送信可能な状態にエンコーディングしてくれているので、UTF8 を使う必要がないと言えば無いのですが、ちょっとデバッグ目的で使いたて……ですね…… (もごもご)