テクノロジー · 実用ガイド

jq の素通しは成功するのに ID が変わる?BigInt の前に実際の処理を検証

恒等フィルターが通っても、算術演算で末尾の桁が変わることがあります。生の出力を対にして比べ、下流の復元処理が問題を見えにくくする前に損失箇所を特定します。

jq と Node の8ケースの正確な桁を比較するイラスト
独自の実測イラスト。早い文字列化と後からの変換を比較。本結果の対象は jq1.7/Node24.22.1 のローカル入力のみです。 Watch at Ease

ID の末尾が変わったら、パーサーを替える前に各段階の生の出力を保存します。素通しテストの成功だけでは、実際の算術フィルターが全桁を保つとはいえません。

ローカル8ケースで元テキスト、jq 出力、Node 解析の境界を区別し、文字列の期待値で全桁を検証します。

1. 期待する ID を Number に入れない

JSON の元テキスト {"id":9007199254740993,"count":42} から始め、期待する ID は文字列 "9007199254740993" として保持します。JavaScript の数値リテラルとして書いて Number 同士を比較すると、期待値自体が既に丸められている可能性があります。データを変更する前に、実際の jq、Node 実行ファイル、バージョン、本番フィルターを記録してください。

RFC8259 は実装による範囲・精度の制限を認め、絶対値が 2^53−1 以下の整数を正確に相互運用できる範囲としています。それを超えても表現可能な整数はあり、全ての大きな値が変わるわけではありません。識別子には全桁が必要です。解析成功やもっともらしいログだけでは受け入れ条件を満たしません。

2. 素通しと実際のフィルターを対にする

Linux 上のローカル検証8ケースでは jq1.7 と Nodev24.22.1 を使いました。この入力に jq -c '.' を適用すると元の ...993 が出力され、.id += 0 では ...992 になりました。1.7 のマニュアルは、変更しないリテラルの保持と倍精度算術を区別しています。素通しの成功が証明するのはその操作だけで、全フィルターの安全性ではありません。

各変換の直前・直後に出力されるテキストを保存します。この実行ファイルでは .id |= tostring が "9007199254740993"、.id += 0 | .id |= tostring が "9007199254740992" を生成しました。先に文字列化する場合と後から行う場合は別の対照です。本番のフィルターとビルドで再検証してください。他の jq 実装やリリースを保証する結果ではありません。

3. 復元コールバックが受け取った入力を確かめる

通常の JSON.parse の後に id.toString() を呼ぶと ...992 になり、解析済みの値を BigInt に渡しても ...992 でした。キーを指定し BigInt(context.source) を読む復元コールバックは、元の入力と素通し出力から ...993 を取得できました。しかし jq の算術演算後には同じコールバックでも ...992 でした。受け取る数値テキストが既に変わっているためです。

構造が既知の数値 ID に用いたテスト用コールバックは (k,v,c)=>k==='id'&&typeof v==='number'?BigInt(c.source):v です。汎用バリデーターではありません。実環境で context.source の対応を確認し、フィールドのパスと整数トークンの文法を検証します。小数・指数表記は別の取り決めが必要です。数値に見える全ての文字列を変換すると、文字列のままにすべき項目も変わります。

4. 往復全体を検証する

API を管理できるなら、移行前に受信側と文字列 ID を合意します。8番目のケースでは復元した BigInt を明示的に id.toString() でシリアライズし、文字列として受け渡すデータを再解析して全桁を取得しました。これはテスト入力の往復の証明であり、従来の数値スキーマとの互換性を示しません。数量、小数の金額、無関係な項目を黙って変更しないでください。

元の数値テキスト、意図した各受け渡し、最後のスキーマに沿った文字列比較が一致して初めて修正を受け入れます。素通し対照と本番フィルターの回帰テストを両方残し、...993 と ...992、最初に変化した境界を記録します。下流の復元処理では上流の情報損失を戻せません。本検証はローカル入力を使い、実稼働のゲートウェイやブラウザーは試していません。実際の生成側・受信側の各境界で再実行してください。

元の数値、jq 出力、Node 解析の境界を示すイラスト
独自の診断イラスト。各段階の数値テキストを比較します。context.source は現在の入力を読み、以前に失った桁は戻しません。 Watch at Ease