🎃
カスタムコネクタはレスポンスのボディに約18桁以上の数値がある場合正確な結果が取得できない
はっきり解決しそうにないので、カスタムコネクタが思ったように動かなかったときの対処方法をメモ
困ったこと
-
LINE WORKS API をカスタムコネクタ経由で実行したら int64 で定義された boardId、postId が正常に返却されなかった
-
ブラウザで確認した正しい boardId
調査したこと
- 以下のコードを適用し、コード中で正しく値が取得できているか確認した
API 実行直後の値を確認
public class Script : ScriptBase
{
public override async Task<HttpResponseMessage> ExecuteAsync()
{
var apiResponse = await this.Context.SendAsync(this.Context.Request, this.CancellationToken);
var content = await apiResponse.Content.ReadAsStringAsync();
var json = JObject.Parse(content);
this.Context.Logger.LogError($"boardId: {json["boardId"]}");
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = ScriptBase.CreateJsonContent(content)
};
}
}
-
コード中で API 実行直後の状態では正確な値を取得できていた
-
でもカスタムコネクタのレスポンスのボディでは、丸め誤差が発生しているようだった
やったこと
- 何らかの理由でレスポンスが返る時に丸め誤差が発生しているようなので、以下コードを適用し対象の値を数値でなく文字列に変換してあげることで、丸め誤差の発生を防ぐように試みた
レスポンスを return する前に特定の項目だけ数値から文字列に変換
public class Script : ScriptBase
{
public override async Task<HttpResponseMessage> ExecuteAsync()
{
var apiResponse = await this.Context.SendAsync(this.Context.Request, this.CancellationToken);
var content = await apiResponse.Content.ReadAsStringAsync();
// JSONとして解析
var token = JToken.Parse(content);
// オブジェクトルートの場合のみ加工処理を実行
if (token.Type == JTokenType.Object)
{
var rootObject = (JObject)token;
// "boards" 配列の処理
if (rootObject["boards"] is JArray boards)
{
foreach (var board in boards.Children<JObject>())
{
if (board["boardId"] is JValue boardId && boardId.Type == JTokenType.Integer)
{
board["boardId"] = boardId.ToString();
}
}
}
// "posts" 配列の処理
if (rootObject["posts"] is JArray posts)
{
foreach (var post in posts.Children<JObject>())
{
if (post["boardId"] is JValue boardId && boardId.Type == JTokenType.Integer)
{
post["boardId"] = boardId.ToString();
}
if (post["postId"] is JValue postId && postId.Type == JTokenType.Integer)
{
post["postId"] = postId.ToString();
}
}
}
// ルートに存在する数値項目の処理
if (rootObject["boardId"] is JValue rootBoardId && rootBoardId.Type == JTokenType.Integer)
{
rootObject["boardId"] = rootBoardId.ToString();
}
if (rootObject["postId"] is JValue rootPostId && rootPostId.Type == JTokenType.Integer)
{
rootObject["postId"] = rootPostId.ToString();
}
// 正常応答として返却
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = ScriptBase.CreateJsonContent(rootObject.ToString())
};
}
else
{
// ルートがオブジェクトでない場合は空応答を返す(処理は任意)
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = ScriptBase.CreateJsonContent(token.ToString())
};
}
}
}
- レスポンスのボディで丸め誤差の発生を防ぐことができた
余談
途中からサンプルの boardId が変わっていて見づらいけどメモとしてなので許してください
コードを書くと、いろんなケースへの対応を考えないといけないので、できるだけ書きたくない
でも書かないと Id が取れない
Id が取れないと、フロー中で特定のリソースを操作できない
ということでやむを得ずコードを(AIが)書きました
もっと簡単な対応方法があればぜひ教えてください
Discussion