プロフィール
22歳の大学生です、2025/4月から就職してエンジニアをやります
- サッカー好き
- 国内サッカー:柏レイソルサポーター
- 海外サッカー:プレミア、セリエを観戦 Roma推し
- アニメ、漫画好き
- ジャンププラス定期購読者
- ラノベ系のアニメ
- 最近はガンダムにハマる
- ラーメンは二郎系が好み
最近はNestJSで個人開発を進めています
従来のシリアライズ
以前は外部クラスを呼び出してシリアライズしていました。
以下の記事を参考にしてください。
【NestJS × Docker】BigIntのシリアライズエラー、大目に見てくれよ - Do not know how to serialize a BigInt -
簡単に要約すると、serviceクラスでreturnするオブジェクトをわざわざ整形してから返していました。
毎度のように外部クラスを呼び出して、整形していました。
少しアホくさいかもしれませんが、「まあこれでいっか」とも思っていました。
しかしここで問題が発生します。
POSTではシリアライズが通用しない
以下のプログラムを見てほしいです。
async addTodo(TodoDto: TodoDto) {
try {
return await this.prisma.todo.create({
data: {
user: { connect: { id: TodoDto.user_id } },
stock: { connect: { id: TodoDto.stock_id } },
}
});
} catch (error) {
console.error('add Favorite todo:', error);
throw error;
}
}
関数名や変数名は適当に命名したものですので、無視してください。
userとstockというリレーションに基づき、渡されてくるuser_idとstock_idという外部キーを挿入します。
ここからが問題なのですが、postのレスポンスではここで作成されたレコードが返ってきます。
ですがservice層でPOSTのレスポンスを整形することはできません。
これまでGETでレスポンスをくれるものをservice層で整形していましたが、POSTではどうしよう、困ったものです。
グローバルインターセプターの介入
もう面倒なので、全てのレスポンスを整形しようと思いました。
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common";
import { map, Observable } from "rxjs";
@Injectable()
export class BigIntToStringInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler<any>): Observable<any> | Promise<Observable<any>> {
return next.handle().pipe(
map((data) => this.convertBigInt(data))
);
}
private convertBigInt(value: any): any {
if (typeof value === 'bigint') {
return value.toString();
}
if (Array.isArray(value)) {
return value.map((item) => this.convertBigInt(item));
}
if (value !== null && typeof value === 'object') {
for (const key in value) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
value[key] = this.convertBigInt(value[key]);
}
}
}
return value;
}
}
これがグローバルインターセプターです。
NestInterceptorをインターフェースとして呼び出し、interceptメソッドで次のハンドラの実行を制御しつつ、レスポンスの整形も行います。
整形自体はconvertBigIntメソッドで行われています。
渡されてきた値、配列、オブジェクトにあるBigInt型の値を文字列に変換する処理を行っています。
そして肝心なのはここからです。
以下のようにmain.tsに追記します。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { BigIntToStringInterceptor } from './infrastructure/utils/BigIntToStringInterceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
//ここが追記
app.useGlobalInterceptors(new BigIntToStringInterceptor());
await app.listen(3000);
}
bootstrap();
これで全レスポンスに整形をかけられる仕様となりました。
終わり
BigIntのシリアライズは面倒です。
困ったことがあったらchatGPTをフル活用して学習を進めています。
自分はchatGPT plusに課金しているため、o3-mini-highモデルを利用しているのですが、これがすごい優れもの。
NestJSは比較的日本語の情報が少ないと有名のフレームワークですが、このモデルがあればそんなことは困らない
ものすごく良いペースで進められていると感じています。
AIに教えられたことはなるべくこのQiitaでの発信などを通して噛み砕くようにしています。
openAI最高