JSON পার্স এরর ঠিক করার উপায়: Unexpected token ধাপে ধাপে যাচাই
সংক্ষেপে: JSON.parse এররকে লাইন ও অক্ষরে অনুবাদ করুন, তারপর ছয়টি কারণ বাদ দিন: ট্রেইলিং কমা, সিঙ্গেল কোট, কমেন্ট, কন্ট্রোল ক্যারেক্টার, BOM ও কাটা-পড়া বিষয়বস্তু।

মূল কথা: পার্স এররে দেখানো লাইন ও কলাম পড়ে প্রথম অবৈধ অক্ষরটি খুঁজুন, তারপর ঠিক করুন তা বাদ পড়া কোট, বাদ পড়া কমা, ট্রেইলিং কমা, BOM নাকি কাটা-পড়া বিষয়বস্তু — শুরু থেকে পুরো ডকুমেন্ট আবার পড়বেন না।
এরর মেসেজ কখনো "কী ভুল" বলে না; এটি কেবল বলে "পার্সার কোথায় আর এগোতে পারেনি"। সেই দুই অবস্থান প্রায়ই এক জায়গা নয়।
১. আগে এররকে কোঅর্ডিনেটে অনুবাদ করুন
একই ভাঙা JSON বিভিন্ন ভাষায় সম্পূর্ণ ভিন্ন এরর দেয়, তবে সবগুলোকেই "কোন লাইন, কোন অক্ষর" তে রূপান্তর করা যায়:
| পরিবেশ | সাধারণ এরর | কীভাবে পড়বেন |
|---|---|---|
| ব্রাউজার / Node | Unexpected token } in JSON at position 42 |
position হলো ০-ভিত্তিক অক্ষর অফসেট, লাইন নম্বর নয় |
| Node 20+ | Unexpected non-whitespace character after JSON at position 42 |
বোঝায় প্রথম অংশ বৈধ, বাড়তি বিষয়বস্তু ৪২-এর পরে শুরু |
| Java Jackson | Unexpected character ('}' (code 125)): was expecting ... at [Source: (String)..."..." ; line: 3, column: 1] |
সরাসরি লাইন ও কলাম দেয়, সবচেয়ে ব্যবহারযোগ্য |
| Python | json.decoder.JSONDecodeError: Expecting ',' delimiter: line 3 column 1 (char 42) |
char হলো অফসেট; লাইন ও কলামই আসল |
| Go | invalid character '}' looking for beginning of object key string |
কেবল অক্ষর দেয়, তাই নিজে পিছিয়ে গিয়ে খুঁজতে হয় |
position পেলে JSON-টি অনলাইন JSON পার্সার-এ পেস্ট করুন; টুল কার্সর এরর লোকেশনে বসায় এবং লাইন ও কলাম নম্বর হাইলাইট করে — এই এক ধাপেই ৯০% অক্ষর মিলিয়ে দেখার ঝামেলা বাঁচে।
২. ছয়টি উচ্চ-ফ্রিকোয়েন্সি এরর
১. ট্রেইলিং কমা
{
"name": "json",
"version": 1,
}
}-এর আগে একটি বাড়তি কমা আছে। JSON স্পেসিফিকেশন ট্রেইলিং কমার অনুমতি দেয় না, কিন্তু JavaScript অবজেক্ট লিটেরাল দেয়, তাই কোড থেকে কপি করা কনফিগারেশনে এটি থাকার সম্ভাবনা সবচেয়ে বেশি। সমাধান: শেষ কমাটি মুছুন; এই ডেটা যদি শুরুতেই JS ফাইলে থাকে, জোর করে JSON বানানোর বদলে JSON5 রূপান্তর ব্যবহার করুন।
২. সিঙ্গেল কোট ও আনকোয়োটেড কি
{ 'name': 'json' }
{ name: "json" }
JSON স্ট্রিং কেবল ডাবল কোট ব্যবহার করতে পারে, আর কি-ও অবশ্যই ডাবল কোটে মোড়া স্ট্রিং হতে হবে। এ দুটি JSON5 / JavaScript-এর শিথিল সিনট্যাক্স, JSON নয়। স্ট্রিংয়ের ভেতরের ডাবল কোট \" এবং ব্যাকস্ল্যাশ \\ হিসেবে লিখতে হবে।
৩. কমেন্ট
{
// টাইমআউট মিলিসেকেন্ডে
"timeout": 3000
}
RFC 8259-এর ব্যাকরণে কমেন্টের কোনো জায়গা নেই। হয় কমেন্ট মুছুন, বা .jsonc / .json5 হিসেবে সেভ করে কমেন্ট-সমর্থক পার্সার ব্যবহার করুন। বিভিন্ন "কমেন্ট স্কিম"-এর সমঝোতার জন্য দেখুন JSON-এ কমেন্ট লেখার উপায়।
৪. স্ট্রিংয়ের ভেতরে কাঁচা নিউলাইন ও কন্ট্রোল ক্যারেক্টার
{"sql": "SELECT *
FROM t"}
JSON স্ট্রিংয়ে কাঁচা লাইন ফিড, ট্যাব বা U+0000–U+001F কন্ট্রোল ক্যারেক্টার থাকতে পারে না; এগুলো \n, \t, \u0009 হিসেবে লিখতে হবে। বহু-লাইনের টেক্সট JSON-এ ঢোকানোর সময় আগে এডিটরে একবার এস্কেপ করুন, বা JSON মিনিফাই ও এস্কেপ দিয়ে সমভাবে হ্যান্ডল করুন।
৫. BOM হেডার
Windows নোটপ্যাডে সেভ করা UTF-8 তিনটি বাইট EF BB BF বহন করে। JSON.parse BOM-এ পেলে Unexpected token দেয়, আর চোখে তা দেখাই যায় না। চেনার উপায়: ফাইলের হেডার হেক্সে দেখুন, বা বিষয়বস্তু অনলাইন টুলে কপি করে দেখুন প্রথম অক্ষর হিসেবে দেখাচ্ছে কি না। সমাধান: "UTF-8 without BOM" হিসেবে সেভ করুন।
৬. কাটা-পড়া বিষয়বস্তু
কেবল প্রথম ৪০৯৬ অক্ষর ছাপা লগ, গেটওয়ে কেটে দেওয়া API রেসপন্স, বিঘ্নিত ডাউনলোড — এই শ্রেণির লক্ষণ "এরর শেষে" এবং ব্র্যাকেটের গণনা মেলে না। আগে ব্র্যাকেট গণনা করুন: { ও [-এর ক্লোজিং না মিললে এটি কাটা-পড়া, সিনট্যাক্স এরর নয়। সেক্ষেত্রে কিছু ঠিক করার দরকার নেই — গিয়ে সম্পূর্ণ ডেটা আনুন।
৩. চীনা লেখা ও এস্কেপিং জড়িত দুইটি ভুল সতর্কতা
চীনা লেখা \u4e2d\u6587 হয়ে যাচ্ছে: এটি বৈধ JSON এস্কেপিং, এলোমেলো লেখা নয়। পার্সের পর মান আবার চীনা হয়ে যায়; \u রূপ কেবল কাঁচা স্ট্রিং সরাসরি দেখলে বোঝা যায়। মানুষকে দেখাতে হলে ফরম্যাটিং টুল দিয়ে আউটপুট দিন; চীনা লেখা URL বা লগে টিকে থাকতে হলে কেবল তখন এস্কেপিং কৌশল নিয়ে ভাবুন।
চীনা লেখা 涓枃-এর মতো এলোমেলো হচ্ছে: এটি এনকোডিং সমস্যা, JSON সমস্যা নয়। UTF-8 বাইটকে GBK হিসেবে ডিকোড করলে এই নিয়মিত প্যাটার্ন তৈরি হয় — "একটি চীনা অক্ষরের জায়গায় তিনটি অক্ষর"। রেসপন্স হেডারের Content-Type: application/json; charset=utf-8 দেখুন, এবং ফাইল পড়ার সময় encoding='utf-8' স্পষ্টভাবে দেওয়া আছে কি না দেখুন।
৪. পাঁচ মিনিটের মেরামত প্রবাহ
- টুলে পেস্ট করুন: আগে অনলাইন পার্সার দিয়ে প্রথম এররটি খুঁজুন, একবারে কেবল একটি ঠিক করুন;
- প্রতিটি ঠিক করার পর যাচাই করুন: প্রতিটি পরিবর্তনের পর আবার পার্স করুন, যাতে একসঙ্গে কয়েক জায়গা ঠিক করে নতুন এরর পুরোনোটিকে ঢেকে না দেয়;
- একবার মিনিফাই করুন: Minify দিয়ে হোয়াইটস্পেস সরিয়ে আবার পার্স করুন; এতে "কাঠামোগত এরর" ও "হোয়াইটস্পেস বা নিউলাইন সমস্যা" আলাদা করা যায়;
- কাঠামো তুলনা করুন: কোনো পরিবর্তনের পর হঠাৎ এরর এলে আগের সংস্করণের সঙ্গে JSON diff করুন; পার্থক্য সাধারণত একটি কমা;
- ফিল্ড-পর্যায়ের যাচাই: সিনট্যাক্স পাস করলেও ব্যবসায়িক স্তর প্রত্যাখ্যান করলে (ফিল্ড নেই, টাইপ ভুল), সেটি JSON Schema ভ্যালিডেশন-এর আওতায়, সিনট্যাক্স সমস্যা নয়।
৫. "দেখতে একই" দুটি JSON টুকরোর একটি কেন পার্স হয়, অন্যটি নয়
সবচেয়ে সাধারণ কারণ অদৃশ্য অক্ষর: ফুল-উইড্থ কমা ,, ফুল-উইড্থ কোট “”, নন-ব্রেকিং স্পেস U+00A0, জিরো-উইডথ স্পেস U+200B। পর্দায় এরা অর্ধ-প্রস্থ সমতুল্য অক্ষরের সঙ্গে প্রায় আলাদা করা যায় না, কিন্তু কোনোটিই JSON ব্যাকরণের অংশ নয়।
চেনার একটি উপায়ই আছে: সমস্যা করা অক্ষরের আশপাশের বিষয়বস্তু কপি করে কোড পয়েন্ট বাইটে বাইটে দেখুন। ব্রাউজার কনসোলে নিচের কোড চালালে প্রতিটি অ-ASCII এবং চীনা রেঞ্জের বাইরের অক্ষর তালিকাবদ্ধ হয়:
[...text].filter((ch) => {
const code = ch.codePointAt(0);
return code > 127 && !(code >= 0x4e00 && code <= 0x9fff);
});
আউটপুটে 0x201c (বাম ডাবল কোট), 0xff0c (ফুল-উইড্থ কমা) বা 0x00a0 দেখা গেলে তারাই culprit।
৬. প্রতিরোধ মেরামতের চেয়ে সস্তা
- কমিট করার আগে কনফিগারেশন ফাইলে পার্স চেক চালান; CI-তে এক লাইনই যথেষ্ট:
node -e "JSON.parse(require('fs').readFileSync('config.json','utf8'))"; - API রেসপন্স সিরিয়ালাইজেশন লাইব্রেরি দিয়ে তৈরি করুন; হাতে স্ট্রিং জোড়া লাগাবেন না — হাতে বানানো স্ট্রিংই ট্রেইলিং কমা ও বাদ পড়া কোটের একমাত্র উৎস;
- JSON লগ করার সময় আগে
JSON.stringifyকল করুন, টেমপ্লেটে ইন্টারপোলেট করবেন না, যাতে অর্ধ-লেখা পেলোডকে সম্পূর্ণ মেসেজ ভুল না করা হয়।
সাধারণ প্রশ্ন
JSON সিনট্যাক্স এররের অবস্থান দ্রুত কীভাবে খুঁজব?
পার্সার যে position বা line/column দেয় সেটি নিন; position হলো ০-ভিত্তিক অক্ষর অফসেট, লাইন নম্বর নয়, আর Java Jackson ও Python সরাসরি লাইন ও কলাম দেয়। JSON-টি অনলাইন JSON পার্সার-এ পেস্ট করুন, টুল কার্সর এরর লোকেশনে বসায় এবং লাইন ও কলাম হাইলাইট করে। এরর শুরুতে থাকলে ফাইলের হেডারে BOM আছে কি না এবং অদৃশ্য অক্ষর আছে কি না দেখুন।
কোড থেকে কপি করা কনফিগারেশনে ট্রেইলিং কমা এত সম্ভাব্য কেন?
JSON স্পেসিফিকেশন ট্রেইলিং কমা নিষিদ্ধ করে, অথচ JavaScript অবজেক্ট লিটেরাল অনুমতি দেয়, তাই JS কোড থেকে কপি করা কনফিগারেশনে সহজেই একটি চলে আসে। সমাধান হলো শেষ কমাটি মুছে ফেলা; ডেটা যদি শুরুতেই JS ফাইলের হয়, জোর করে JSON বানানোর চেয়ে JSON5 রূপান্তর বেশি মানানসই।
কমেন্টযুক্ত কনফিগারেশন ফাইলকে সাধারণ JSON হিসেবে পার্স করা যায়?
না — RFC 8259-এর ব্যাকরণে কমেন্টের জায়গা নেই, তাই সরাসরি পার্স করলে এরর হয়। হয় কমেন্ট মুছুন, বা .jsonc / .json5 হিসেবে সেভ করে কমেন্ট-সমর্থক পার্সার ব্যবহার করুন। কমেন্ট স্কিমগুলোর সমঝোতার জন্য দেখুন JSON-এ কমেন্ট লেখার উপায়।