জাভাস্ক্রিপ্টে `JSON` ক্লাস

জাভাস্ক্রিপ্টে `JSON` ক্লাস

এই প্রবন্ধে জাভাস্ক্রিপ্টে JSON ক্লাসটি ব্যাখ্যা করা হয়েছে।

আমরা জাভাস্ক্রিপ্টে JSON ক্লাসটি ব্যবহারিক উদাহরণের মাধ্যমে ব্যাখ্যা করব।

YouTube Video

জাভাস্ক্রিপ্টে JSON ক্লাস

JSON অবজেক্টের প্রধানত দুটি মেথড রয়েছে। JSON.stringify() একটি অবজেক্টকে JSON স্ট্রিংয়ে রূপান্তর করে, এবং JSON.parse() একটি JSON স্ট্রিং থেকে অবজেক্ট তৈরি করে। JSON একটি ডেটা বিনিময় ফরম্যাট যা শুধুমাত্র কিছু জাভাস্ক্রিপ্ট মান প্রকাশ করতে পারে। ফাংশান, undefined, Symbol, এবং সার্কুলার রেফারেন্স সরাসরি JSON এ রূপান্তর করা যায় না।

JSON.stringify()

প্রথমে, অবজেক্টকে JSON স্ট্রিংয়ে রূপান্তরের একটি মৌলিক উদাহরণ এখানে দেওয়া হলো।

1// Convert a JavaScript object to a JSON string.
2const obj = { name: "Alice", age: 30, active: true };
3const jsonString = JSON.stringify(obj);
4console.log(jsonString); // {"name":"Alice","age":30,"active":true}
  • এই কোডটি একটি সাধারণ অবজেক্টকে JSON স্ট্রিংয়ে রূপান্তরের সবচেয়ে মৌলিক উদাহরণ। JSON.stringify স্ট্রিংটি সিঙ্ক্রোনাসভাবে রিটার্ন করে।

JSON.stringify এর দ্বিতীয় আর্গুমেন্ট (replacer)

JSON.stringify-এর দ্বিতীয় আর্গুমেন্ট replacer নির্দিষ্ট করে, আপনি রূপান্তরের নিয়মগুলো সুক্ষ্মভাবে নিয়ন্ত্রণ করতে পারেন। এখানে একটি অ্যারে ব্যবহার করে শুধুমাত্র নির্দিষ্ট প্রপার্টি রাখার উদাহরণ দেওয়া হল।

1// Use a replacer array to include only specific properties during stringification.
2const user = { id: 1, name: "Bob", password: "secret", role: "admin" };
3const safeJson = JSON.stringify(user, ["id", "name", "role"]);
4console.log(safeJson); // {"id":1,"name":"Bob","role":"admin"}
  • এই উদাহরণে, password বাদ দেওয়া হয়েছে যাতে নিরাপদ লগ আউটপুট সম্ভব হয়। নিরাপত্তার কারণে সংবেদনশীল তথ্য সরিয়ে ফেলতে হলে এটি উপকারী।

ভ্যালু রূপান্তর ও ফিল্টারিংয়ের জন্য replacer-কে ফাংশন হিসেবে ব্যবহার

আরও নমনীয়তা চাইলে, আপনি প্রতিটি কী ও ভ্যালু প্রসেস করার জন্য একটি ফাংশন সরবরাহ করতে পারেন। নিচে Date-কে ISO স্ট্রিং হিসেবে রাখার একটি উদাহরণ দেয়া হলো।

 1// Use a replacer function to customize serialization.
 2const data = { name: "Carol", joined: new Date("2020-01-01T12:00:00Z") };
 3const jsonCustom = JSON.stringify(data, (key, value) => {
 4  // Convert Date objects to ISO strings explicitly
 5  if (this && this[key] instanceof Date) {
 6    return this[key].toISOString();
 7  }
 8  return value;
 9});
10console.log(jsonCustom); // {"name":"Carol","joined":"2020-01-01T12:00:00.000Z"}
  • ফাংশন-টাইপ replacer-এ কি এবং মান দেওয়া হয় এবং ফেরত আসা মানটিই চূড়ান্ত JSON এ ব্যবহৃত হয়। this প্যারেন্ট অবজেক্টকে নির্দেশ করে, তাই এটি নেস্টেড রূপান্তরের জন্যও ব্যবহার করা যেতে পারে।

JSON.parse()-এর মৌলিক বিষয়গুলো

JSON.parse একটি JSON স্ট্রিংকে আবার অবজেক্টে রূপান্তর করে। try/catch দিয়ে ঘিরে ফেলুন, যাতে অবৈধ JSON অ্যারর হ্যান্ডল করতে পারেন।

1// Parse a JSON string into an object and handle parsing errors.
2const jsonText = '{"title":"Example","count":42}';
3try {
4  const parsed = JSON.parse(jsonText);
5  console.log(parsed.title); // Example
6} catch (err) {
7  console.error("Invalid JSON:", err.message);
8}
  • স্ট্রিংটি অবৈধ হলে, একটি এক্সসেপশন ছুঁড়ে দেওয়া হবে, তাই বাইরের সোর্স ব্যবহারে সবসময় এক্সসেপশন হ্যান্ডলিং রাখা দরকার।

reviver ব্যবহার করে কাস্টম রিস্টোরেশন (যেমন Date রিস্টোরের উদাহরণ)

JSON.parse-এর দ্বিতীয় আর্গুমেন্ট reviver ব্যবহার করে আপনি মান পুনরুদ্ধার করতে পারেন। নিচে সংরক্ষিত স্ট্রিং ডেটকে আবার Date অবজেক্টে রূপান্তরের একটি উদাহরণ দেওয়া হলো।

 1// Use a reviver to turn ISO date strings back into Date objects.
 2const jsonWithDate = '{"name":"Dana","joined":"2021-06-15T09:00:00.000Z"}';
 3const obj = JSON.parse(jsonWithDate, (key, value) => {
 4  // A simple check for ISO date-like strings
 5  if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
 6    return new Date(value);
 7  }
 8  return value;
 9});
10console.log(obj.joined instanceof Date); // true
  • প্রতিটি কী-এর জন্য reviver ডাকা হয় এবং ফিরতি মানটি চূড়ান্ত অবজেক্টে ব্যবহৃত হয়। আপনার অ্যাপ্লিকেশন অনুযায়ী কড়া ডেট ফরম্যাট চেক করুন।

প্রিটি-প্রিন্ট এবং space আর্গুমেন্ট

পাঠযোগ্যতার জন্য ইনডেন্টসহ আউটপুট করতে, JSON.stringify-এর তৃতীয় আর্গুমেন্ট হিসেবে একটি সংখ্যা বা স্ট্রিং পাঠান।

1// Pretty-print an object with 2-space indentation for readability.
2const config = { host: "localhost", port: 3000, debug: true };
3const pretty = JSON.stringify(config, null, 2);
4console.log(pretty);
5/* {
6  "host": "localhost",
7  "port": 3000,
8  "debug": true
9} */
  • যেসব JSON মানুষের দ্বারা পড়ার জন্য, যেমন লগ বা কনফিগারেশন ফাইল, সেখানে ইনডেন্টেশন নির্ধারণ করা সহায়ক। তবে, মনে রাখবেন এতে ডেটার সাইজ বৃদ্ধি পায়।

সার্কুলার রেফারেন্স কিভাবে হ্যান্ডল করবেন

যদি সার্কুলার রেফারেন্স থাকে, JSON.stringify একটি TypeError ছুঁড়ে দেয়। সাধারণ সমাধান হলো সার্কুলার রেফারেন্স এড়াতে seen সেট ব্যবহার করে একটি replacer তৈরি করা।

 1// Safely stringify objects that may contain circular references.
 2function safeStringify(value) {
 3  const seen = new WeakSet();
 4  return JSON.stringify(value, (key, val) => {
 5    if (val && typeof val === "object") {
 6      if (seen.has(val)) return "[Circular]";
 7      seen.add(val);
 8    }
 9    return val;
10  });
11}
12
13const a = { name: "A" };
14a.self = a;
15console.log(safeStringify(a)); // {"name":"A","self":"[Circular]"}
  • WeakSet ব্যবহারে মেমোরি লিক এড়িয়ে সার্কুলার রেফারেন্স শনাক্ত করা যায়। সার্কুলার রেফারেন্সের ক্ষেত্রে এটি "[Circular]" রিটার্ন করে। "[Circular]"-এর পরিবর্তে একটি রেফারেন্স আইডি দেওয়াও সম্ভব।

toJSON মেথড দিয়ে কাস্টম সিরিয়ালাইজেশন

অবজেক্টে toJSON মেথড সংজ্ঞায়িত করলে, JSON.stringify সেটার রিটার্ন মান ব্যবহার করে। প্রত্যেক টাইপের জন্য রূপান্তর নিয়ম এমবেড করতে চাইলে এটি উপকারী।

 1// Define toJSON on a class to customize its JSON representation.
 2class Point {
 3  constructor(x, y) {
 4    this.x = x;
 5    this.y = y;
 6  }
 7  toJSON() {
 8    // This will be used by JSON.stringify
 9    return { x: this.x, y: this.y, type: "Point" };
10  }
11}
12
13const p = new Point(10, 20);
14console.log(JSON.stringify(p)); // {"x":10,"y":20,"type":"Point"}
  • toJSON দিয়ে অবজেক্ট লেভেলে সিরিয়ালাইজেশন নিয়ম সংজ্ঞায়িত করা যায়, যা replacer-এর তুলনায় আরো স্থানীয় ও স্বতঃবোধগম্য।

JSON-এর সীমাবদ্ধতা ও সাবধানতা

নোটযোগ্য যেগুলো JSON এ রূপান্তর করা যায় না: undefined, ফাংশন, Symbol, BigInt, এবং সার্কুলার রেফারেন্স। সংখ্যার নির্ভুলতা সম্পর্কেও সাবধান (যেমন: বড় পূর্ণসংখ্যা বা IEEE ফ্লোটিং পয়েন্ট রাউন্ডিং)।

 1// Demonstrate values that can't be represented in JSON.
 2const sample = {
 3  a: undefined,
 4  b: function () {},
 5  c: Symbol("s"),
 6  d: 9007199254740993n // BigInt (note: JSON.stringify will throw on BigInt)
 7};
 8// JSON.stringify will throw for BigInt and will drop undefined, functions, symbols in objects.
 9try {
10  console.log(JSON.stringify(sample));
11} catch (err) {
12  console.error("Error during stringify:", err.message);
13}
  • BigInt ব্যবহারে, এটিকে স্ট্রিংয়ে রূপান্তর করুন অথবা কাস্টম replacer বা toJSON দিয়ে প্রদর্শন নির্ধারণ করুন।

নিরাপত্তা (অবিশ্বস্ত JSON ব্যবহারের সময়)

JSON.parse নিজেই নিরাপদ ও eval-এর তুলনায় বেশি নিরাপদ, তবে পার্স করা অবজেক্টে অন্ধবিশ্বাস করে সরাসরি প্রপার্টি অ্যাক্সেস বা ডেটাবেস কোয়েরিতে ব্যবহার ঝুঁকিপূর্ণ। ডেটা প্রত্যাশিত স্কিমার সাথে মেলে কিনা তা সবসময় যাচাই করুন।

1// Parse external JSON and validate expected properties before use.
2const external = '{"username":"eve","role":"user"}';
3const parsed = JSON.parse(external);
4if (typeof parsed.username === "string" && ["user","admin"].includes(parsed.role)) {
5  console.log("Safe to use parsed.username and parsed.role.");
6} else {
7  throw new Error("Invalid payload");
8}
  • ইনপুট যাচাই (স্কিমা ভ্যালিডেশন) করতে ajv-এর মতো লাইব্রেরি ব্যবহার করা শক্তপোক্ত সমাধান।

কর্মদক্ষতা বিবেচনা

বড় অবজেক্ট বারবার সিরিয়ালাইজ/ডিসিরিয়ালাইজ করলে CPU ও মেমোরিতে চাপ দেয়। প্রয়োজন হলে, শুধু পার্থক্য পাঠানো, বাইনারি ফরম্যাট (যেমন MessagePack) ব্যবহার, বা স্ট্রিমিং-এ (ধাপে ধাপে ডেটা প্রসেস) বিবেচনা করতে পারেন। ব্রাউজার পরিবেশে, structuredClone (কপি করার জন্য) বা postMessage-এ ট্রান্সফারেবল অবজেক্ট ব্যবহার করা যায়।

নির্দিষ্ট পরামর্শ (সংক্ষেপে)

এছাড়াও নিম্নলিখিত বিষয়গুলো বিবেচনা করতে পারেন:।

  • লগের ক্ষেত্রে প্রিটি-প্রিন্ট পরিহার করুন এবং সাইজ কমাতে একলাইন JSON ব্যবহার করুন।
  • যেগুলো প্রায়ই সিরিয়ালাইজ হয়, সেগুলোকে আগে থেকেই হালকা করা উচিত; যেমন অপ্রয়োজনীয় প্রপার্টি অপসারণ।
  • ট্র্যাভার্সাল কমাতে এবং অপ্রয়োজনীয় প্রপার্টি বাদ দিতে replacer ব্যবহার করুন।

ব্যবহারিক উদাহরণ: API অনুরোধ পাঠানো/গ্রহণ করার ধারা

শেষে, সার্ভারে পাঠানোর জন্য অবজেক্টকে নিরাপদে JSON-এ রূপান্তর এবং প্রাপ্ত রেসপন্স থেকে date পুনরুদ্ধারের একটি ধারা দেখানো হলো।

 1// Prepare payload, stringify safely, send via fetch, and revive dates on response.
 2async function sendUserUpdate(url, user) {
 3  // Remove sensitive info before sending
 4  const payload = JSON.stringify(user, (k, v) => (k === "password" ? undefined : v));
 5  const res = await fetch(url, {
 6    method: "POST",
 7    headers: { "Content-Type": "application/json" },
 8    body: payload
 9  });
10
11  const text = await res.text();
12  // Reviver: convert ISO date strings back to Date
13  const data = JSON.parse(text, (key, value) => {
14    if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
15      return new Date(value);
16    }
17    return value;
18  });
19  return data;
20}
  • এই উদাহরণে পাঠানোর আগে password বাদ দেয়া হয়েছে, এবং গ্রহণের পরে date reviver দিয়ে পুনরুদ্ধার করা হয়েছে। বাস্তব ব্যবহারে, আপনাকে এরর হ্যান্ডলিং এবং টাইমআউট প্রসেসিং যোগ করতে হবে।

সারসংক্ষেপ

JSON.stringify()JSON.parse() ব্যবহার করে আপনি অবজেক্ট ও স্ট্রিংয়ের মধ্যে রূপান্তর করতে পারেন। আপনি replacerreviver-এর মাধ্যমে রূপান্তর প্রক্রিয়া কাস্টমাইজ করতে পারেন, এবং ক্লাসে toJSON ইমপ্লিমেন্ট করলে প্রতিটি অবজেক্ট আলাদাভাবে নিয়ন্ত্রণও করা যাবে। সার্কুলার রেফারেন্স, BigInt, ফাংশন ইত্যাদি সরাসরি হ্যান্ডল করা যায় না, এজন্য আগেই এদের প্রসেস করতে হবে।

বাইরের ইনপুট সবসময় যাচাই করুন এবং যাতে সংবেদনশীল তথ্য লগ বা যোগাযোগে না আসে নিশ্চিত করুন। ডেটার সাইজ বড় হলে প্রিটি-প্রিন্ট পরিহার করুন, পার্থক্য পাঠানোর কৌশল নিন অথবা বাইনারি ফরম্যাট ব্যবহারের কথা ভাবুন।

আপনি আমাদের ইউটিউব চ্যানেলে ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করে উপরের নিবন্ধটি অনুসরণ করতে পারেন। দয়া করে ইউটিউব চ্যানেলটিও দেখুন।

YouTube Video