JSON Toolkit

বড় ইন্টিজার কেন নির্ভুলতা হারায়

সংক্ষেপে: 2^53-1-এর বেশি ইন্টিজার `JSON.parse`-এ নির্ভুলতা হারায়। Snowflake ID, অর্ডার নম্বর ও ডেটাবেস bigint — সবই এতে পড়ে, তাই শুরু থেকে শেষ পর্যন্ত স্ট্রিং হিসেবে রাখুন।

মধ্যবর্তী~4 মিনিট পড়াপ্রকাশ 2026-10-30আপডেট 2026-11-04
JSON-এ বড় ইন্টিজার কেন নির্ভুলতা হারায় ও কীভাবে রাখবেন

মূল কথা: snowflake ID, অর্ডার নম্বর ও bigint প্রাইমারি কি-কে সিরিয়ালাইজেশন, পরিবহন ও পার্সিং জুড়ে স্ট্রিং ধরুন; সংখ্যিক টাইপ কেবল তখনই রাখুন যখন ফিল্ড 2^53-1-এর মধ্যে থাকবে প্রমাণিত, আর তখন Schema-তে maximum বাধ্যবাধকতা দিয়ে তা বলবৎ করুন।

কারণ ক্ষতিটা পার্সিংয়ের সময়েই হয়, নীরবে।

JSON.parse('{"id": 9007199254740993}');
// { id: 9007199254740992 }

হারানো অঙ্ক চলে গেছে; ফেরানোর কিছু নেই।

2^53 কোথা থেকে আসে

JavaScript-এ একটাই সংখ্যিক টাইপ: IEEE 754 ডাবল-প্রিসিশন, ৫৩ বিট significand (একটি অন্তর্নিহিত, ৫২ স্পষ্ট)। তাই নিখুঁত ইন্টিজার থামে ±(2^53-1)-এ:

-9007199254740991 .. 9007199254740991

ওই রেখার উপরে পরপর প্রকাশযোগ্য মান ২, ৪, ৮ দূরে। 9007199254740993 বিজোড়, আর ওই মাত্রায় প্রতিটি প্রকাশযোগ্য মান জোড়, তাই এটি 9007199254740992-এ রাউন্ড হয়।

যে ফিল্ডগুলোতে লাগে

ফিল্ড অঙ্ক ঝুঁকি
Snowflake ID ১৮–১৯ বেশি, শেষ অঙ্ক বদলায়
অর্ডার / লেনদেন নম্বর ১৬–২০ বেশি
ডেটাবেস bigint প্রাইমারি কি ১৯ বেশি
উপ-এককে টাকা — কম
মিলিসেকেন্ড টাইমস্ট্যাম্প ১৩ নিরাপদ

সাধারণ সূত্র: এগুলো আইডেন্টিফায়ার, পরিমাণ নয়। আইডেন্টিফায়ার পরিবাহিত হয়, কখনো যোগ বা গুণ হয় না, তাই স্ট্রিং-ই সঠিক টাইপ।

চারটি সমাধান

স্ট্রিং হিসেবে সিরিয়ালাইজ করুন। ব্যাকএন্ড রেসপন্স লেখার আগে bigint ফিল্ড রূপান্তর করে। সরল ও টেকসই; ডকুমেন্ট করুন এই ফিল্ডগুলো স্ট্রিং।

সিরিয়ালাইজারকে সামলাতে দিন। Long-এর জন্য Jackson-এর ToStringSerializer, Go-র json:",string" ট্যাগ। একই ধারণা: মানকে সংখ্যিক পথের বাইরে রাখুন।

BigInt সমর্থনসহ পার্স করুন। json-bigint ও অনুরূপ লাইব্রেরি। খেয়াল করুন BigInt Number পাটিগণিতের সঙ্গে মেশানো যায় না, আর JSON.stringify এটি প্রত্যাখ্যান করে।

রেঞ্জ সীমিত করুন। ফিল্ড সত্যিই 2^53 ছাড়াতে না পারলে Schema-তে maximum যোগ করুন যাতে রেঞ্জের বাইরের ডেটা ভ্যালিডেশনে ব্যর্থ হয়, ব্রাউজারে নীরবে ব্যর্থ না হয়ে।

এই বাগ আছে কি না কীভাবে বুঝবেন

একটি জানা ID নিয়ে round-trip করুন: সিরিয়ালাইজ, পাঠান, পার্স, অক্ষর ধরে ধরে তুলনা। বা কাঁচা রেসপন্স বডি দেখুন — কোট ছাড়া ১৯-অঙ্কের সংখ্যা ভুল শেষ অঙ্ক নিয়ে এলে প্রায় নিশ্চিতভাবে পার্স-সময়ের ক্ষতি।

সাধারণ প্রশ্ন

JSON.parse এরর ছাড়াই শেষ অঙ্ক বদলায় কেন?

JavaScript-এ একটাই সংখ্যিক টাইপ, IEEE 754 ডাবল-প্রিসিশন, তাই 2^53-1-এর বেশি ইন্টিজার কেবল নিকটতম প্রকাশযোগ্য মানে পড়তে পারে। JSON.parse এটিকে সাধারণ সংখ্যিক রূপান্তর ধরে: throw করে না, সতর্কও করে না।

ফ্রন্টএন্ড বড় ইন্টিজার অক্ষত কীভাবে রাখবে?

json-bigint-এর মতো লাইব্রেরি ব্যবহার করুন, কারণ JSON.parse তা পারে না। দাম হলো BigInt Number পাটিগণিতের সঙ্গে মেশানো যায় না আর JSON.stringify প্রত্যাখ্যান করে, তাই আশপাশের কোডও বদলাতে হয়।

API ডকে বলা উচিত এই ফিল্ডগুলো স্ট্রিং?

হ্যাঁ। স্ট্রিংয়ে সিরিয়ালাইজ করা সরলতম ও টেকসই সমাধান, কিন্তু তা কেবল কাজ করে যদি ভোক্তারা মানকে টেক্সট ধরে, তাই ফিল্ড টাইপ API চুক্তিতে লিখতে হবে।

আরও পড়ুন