الكائن JSON في JavaScript

من موسوعة حسوب

الكائن JSON يحتوي على الدوال التي تُفسِّر صيغة JavaScript Object Notation (اختصارًا JSON) وتحوّل القيم إلى صيغة JSON. ليس الغرض من هذا الكائن هو تهيئته أو بناؤه (عبر المعامل new)، وليس له عملٌ خاصٌ به باستثناء وجود دالتين تابعتين له.

الوصف

صيغة JSON هي صيغة لتخزين الكائنات والمصفوفات والأعداد والسلاسل النصية والقيم المنطقية والقيمة null؛ وهي مبنية على صيغة JavaScript لكنها تختلف عنها، فبعض شيفرات JavaScript ليست صالحةً في JSON، وبعض شيفرات JSON ليس صالحةً في JavaScript.

الجدول الآتي يعرض بعض الاختلافات بين JavaScript و JSON عند التعامل مع أنواع البيانات:

نوع البيانات في JavaScript الاختلاف في JSON
الكائنات والمصفوفات يجب أن تُحاط أسماء الخاصيات بعلامتَي اقتباس مزدوجتين، ولا يُسمَح بوضع فاصلة بعد آخر عنصر.
الأعداد لا يُسمَح باستخدام الأصفار السابقة للأعداد (إذ سيتم تجاهل الأصفار في دالة JSON.stringify، لكن الدالة JSON.parse سترمي الخطأ SyntaxError). ويجب أن تُتبَع الفاصلة العشرية برقم واحد على الأقل.
السلاسل النصية لا يُسمَح إلا باستخدام مجموعة فرعية من المحارف المُهرَّبة، ومن الممنوع استخدام بعض محارف التحكم، ويجب أن تكون السلاسل النصية محطاة بعلامتَي اقتباس مزدوجتين. انظر المثال الآتي الذي تعمل فيها الدالة JSON.parse دون مشاكل لكن سيرمى الخطأ SyntaxError عند محاولة تفسير السلسلة النصية كشيفرة JavaScript:
var code = '"\u2028\u2029"';
JSON.parse(code); // تعمل دون مشاكل
eval(code); // تفشل

هذه كامل صيغة JSON:

JSON = null
    or true or false
    or JSONNumber
    or JSONString
    or JSONObject
    or JSONArray

JSONNumber = - PositiveNumber
          or PositiveNumber
PositiveNumber = DecimalNumber
              or DecimalNumber . Digits
              or DecimalNumber . Digits ExponentPart
              or DecimalNumber ExponentPart
DecimalNumber = 0
             or OneToNine Digits
ExponentPart = e Exponent
            or E Exponent
Exponent = Digits
        or + Digits
        or - Digits
Digits = Digit
      or Digits Digit
Digit = 0 through 9
OneToNine = 1 through 9

JSONString = ""
          or " StringCharacters "
StringCharacters = StringCharacter
                or StringCharacters StringCharacter
StringCharacter = any character
                  except " or \ or U+0000 through U+001F
               or EscapeSequence
EscapeSequence = \" or \/ or \\ or \b or \f or \n or \r or \t
              or \u HexDigit HexDigit HexDigit HexDigit
HexDigit = 0 through 9
        or A through F
        or a through f

JSONObject = { }
          or { Members }
Members = JSONString : JSON
       or Members , JSONString : JSON

JSONArray = [ ]
         or [ ArrayElements ]
ArrayElements = JSON
             or ArrayElements , JSON

الدوال

JSON.parse()‎

تفسير سلسلة نصية بصيغة JSON، ويمكن اختياريًا تحويل القيمة والخاصيات، ثم إعادة الناتج.

JSON.stringify()‎

إعادة سلسلة نصية بصيغة JSON التي ترتبط بالقيمة المُحدَّدة، ويمكن اختياريًا جعلها تحتوي على خاصيات معيّنة، أو تستبدل قيم الخاصيات كما يريد المستخدم.

تعويض نقص دعم المتصفحات

الكائن JSON لم يكن مدعومًا في المتصفحات القديمة؛ ويمكن الالتفاف على هذه المشكلة بإضافة الشيفرة الآتية في بداية السكربتات، مما يسمح باستخدام كائن JSON في المتصفحات التي لا تدعمه (مثل الإصدارات القديمة من متصفح IE).

الخوارزمية الآتية تحاكي الكائن JSON:

if (!window.JSON) {
  window.JSON = {
    parse: function(sJSON) { return eval('(' + sJSON + ')'); },
    stringify: (function () {
      var toString = Object.prototype.toString;
      var hasOwnProperty = Object.prototype.hasOwnProperty;
      var isArray = Array.isArray || function (a) { return toString.call(a) === '[object Array]'; };
      var escMap = {'"': '\\"', '\\': '\\\\', '\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t'};
      var escFunc = function (m) { return escMap[m] || '\\u' + (m.charCodeAt(0) + 0x10000).toString(16).substr(1); };
      var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
      return function stringify(value) {
        if (value == null) {
          return 'null';
        } else if (typeof value === 'number') {
          return isFinite(value) ? value.toString() : 'null';
        } else if (typeof value === 'boolean') {
          return value.toString();
        } else if (typeof value === 'object') {
          if (typeof value.toJSON === 'function') {
            return stringify(value.toJSON());
          } else if (isArray(value)) {
            var res = '[';
            for (var i = 0; i < value.length; i++)
              res += (i ? ', ' : '') + stringify(value[i]);
            return res + ']';
          } else if (toString.call(value) === '[object Object]') {
            var tmp = [];
            for (var k in value) {
              // in case "hasOwnProperty" has been shadowed
              if (hasOwnProperty.call(value, k))
                tmp.push(stringify(k) + ': ' + stringify(value[k]));
            }
            return '{' + tmp.join(', ') + '}';
          }
        }
        return '"' + value.toString().replace(escRE, escFunc) + '"';
      };
    })()
  };
}

لحلول أكثر تعقيدًا لإضافة دعم لكائن JSON، فانظر إلى JSON2 و JSON3.

دعم المتصفحات

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي نعم 3.5 8 10.5 4

مصادر ومواصفات