فانکشن ()toJSON در جاوااسکریپت چیست؟

ترجمه و تالیف : ابوالفضل باغشاهی
تاریخ انتشار : 21 تیر 99
خواندن در 1 دقیقه
دسته بندی ها : جاوا اسکریپت

در جاوااسکریپت، فانکشن ()JSON.stringify به دنبال فانکشن ()toJSON در آبجکت مورد نظر می‌گردد. اگر آبجکتی دارای فانکشن ()toJSON باشد، ()JSON.stringify فانکشن ()toJSON را فراخوانی کرده و مقدار بازگشتی را از ()toJSON باز می‌گرداند.

به عنوان مثال قطعه کد زیر همان چیزی را چاپ می کند که ({JSON.stringify({ answer: 42 چاپ می کند.

const json = JSON.stringify({
  answer: { toJSON: () => 42 }
});

console.log(json); // {"answer":42}

با استفاده از کلاس های ES6:

کاربرد فانکشن ()toJSON در اطمینان از سریال شدن صحیح کلاس های ES6 است. برای مثال تصور کنید که یک کلاس سفارشی و شخصی برای ارورها دارید. 

class HTTPError extends Error {
  constructor(message, status) {
    super(message);
    this.status = status;
  }
}

به طور پیش‌فرض جاوااسکریپت با سریال کردن ارورها میانه‌ی خوبی ندارد. قطعه کد زیر، {"status":404} را بدون هیچ پیام خطا یا استک تریسی چاپ می‌کند.

class HTTPError extends Error {
  constructor(message, status) {
    super(message);
    this.status = status;
  }
}

const e = new HTTPError('Fail', 404);
console.log(JSON.stringify(e)); // {"status":404}

اما اگر شما یک متد ()toJSON به کلاس HTTPError اضافه کنید، متوجه می‌شوید که جاوا اسکریپکت چگونه نمونه‌های کلاس HTTPError را سریال می‌کند.

class HTTPError extends Error {
  constructor(message, status) {
    super(message);
    this.status = status;
  }

  toJSON() {
    return { message: this.message, status: this.status };
  }
}

const e = new HTTPError('Fail', 404);
console.log(JSON.stringify(e)); // {"message":"Fail","status":404}

شما حتی می‌توانید اگر دوست دارید، ()toJSON را مجبور به سریال کردن استک تریس کنید. البته در حالتی که NODE_ENV را development قرار داده باشید.

class HTTPError extends Error {
  constructor(message, status) {
    super(message);
    this.status = status;
  }

  toJSON() {
    const ret = { message: this.message, status: this.status };
    if (process.env.NODE_ENV === 'development') {
      ret.stack = this.stack;
    }
    return ret;
  }
}

const e = new HTTPError('Fail', 404);
// {"message":"Fail","status":404,"stack":"Error: Fail\n    at ...
console.log(JSON.stringify(e));

یک نکته‌ی مثبت درباره‌ی ()toJSON این است که جاوااسکریپت، حالت بازگشتی را برای شما مدیریت می‌کند؛ در نتیجه نمونه‌های پیچیده‌ی تودرتو از HTTPError و همچنین نمونه‌هایی از HTTPError که درون آرایه قرار دارند،‌ به شکل صحیح سریال می شوند.

class HTTPError extends Error {
  constructor(message, status) {
    super(message);
    this.status = status;
  }

  toJSON() { 
    return { message: this.message, status: this.status };
  }
}

const e = new HTTPError('Fail', 404);
// {"nested":{"message":"Fail","status":404},"arr":[{"message":"Fail","status":404}]}
console.log(JSON.stringify({
  nested: e,
  arr: [e]
}));

کتاب‌خانه‌ها و فریمورک‌های فراوانی از ()JSON.Stringify در پشت صحنه‌ی خود و درون ساختارشان استفاده می‌کنند. برای مثال در فریمورک Express فانکشن ()res.json و همچنین درخواست‌های POST از طریق Axios آبجکت‌ها را با استفاده از ()JSON.stringify به JSON تبدیل می‌کنند؛ در نتیجه فانکشن سفارشی ()toJSON با این ماژول‌ها نیز به خوبی کار می‌کند.

()toJSON در کاربرد

بسیاری از کتاب‌خانه‌ها و فریمورک‌ها از ()toJSON برای اطمینان از سریال شدن صحیح آبجکت‌های پیچیده به یک چیز قابل فهم توسط ()JSON.stringify استفاده می‌کنند. مثلا Moment.js کتاب‌خانه‌ای است که آبجکت‌های آن یک فانکشن ساده‌ی ()toJSON دارند که به شکل زیر است:

 function toJSON () {
        // JSON.stringify(new Date(NaN)) === 'null'
        return this.isValid() ? this.toISOString() : 'null';
    }

خودتان هم می‌توانید این مورد را با کد زیر امتحان کنید:

const moment = require('moment');
console.log(moment('2019-06-01').toJSON.toString());

بافرهای Node.js نیز یک فانکشن ()toJSON دارند.

const buf = Buffer.from('abc');
console.log(buf.toJSON.toString());

// Prints:
function toJSON() {
  if (this.length > 0) {
    const data = new Array(this.length);
    for (var i = 0; i < this.length; ++i)
      data[i] = this[i];
    return { type: 'Buffer', data };
  } else {
    return { type: 'Buffer', data: [] };
  }
}

اسناد Mongoose هم یک فانکشن ()toJSON دارند که اطمینان حاصل می‌کند که حالت درونی اسناد Mongoose تبدیل به خروجی ()JSON.stringify نشوند.

نتیجه‌گیری

فانکشن ()toJSON ابزاری بسیار مهم و کاربردی در ساخت کلاس‌ها در جاوااسکریپت است؛ درواقع نشان‌گر نحوه‌ی ‌کنترل جاوااسکریپت بر روی سریال شدن کلاس شما به JSON است. این فانکشن می‌تواند در موارد بسیار زیادی به کمک ما بیاید. مواردی مانند اطمینان از سریال شدن تاریخ‌ها و بافرهای نود جی اس به شکلی درست در اپلیکیشن شما. دفعه بعدی که دارید یک کلاس ES6 می‌نویسید، حتما از این قابلیت استفاده کنید.

منبع

گردآوری و تالیف ابوالفضل باغشاهی
آفلاین
user-avatar

Front-End

دیدگاه‌ها و پرسش‌ها

برای ارسال نظر لازم است ابتدا وارد سایت شوید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید