В этой статье мы рассмотрим преимущества сериализации объектов, текущие реализации браузеров и разработаем некоторый код, который может помочь вашим проектам на основе Ajax.
Предположим, у нас есть довольно сложный объект JavaScript, определенный с помощью буквенной нотации:
var obj1 = { b1: true, s1: "text string", n1: 12345, n2: null, n3: undefined, a1: [ 1,1,2,3,5,8, [13, 21, 34] ], o1: { a: [3, 2, 1], b: { c: 42, d: [ 3.14, 1.618 ] } } };
Мы можем получить доступ к любому из свойств объекта различными способами:
obj1.s1; // returns "text string" obj1["n1"]; // returns 12345 obj1.a1[6][1]; // returns 21 obj1["o1"]["b"]["c"]; // returns 42
Этот объект также можно передавать в функции и методы JavaScript вместо указания отдельных аргументов. Полезные вещи.
Однако что если нам нужно сохранить этот объект в cookie? Что если нам нужно передать объект веб-сервисам через Ajax-запрос? Что если этот веб-сервис хочет вернуть измененную версию объекта? Ответ сериализации:
- Сериализация — это процесс превращения любого объекта в строку.
- Десериализация превращает эту строку обратно в собственный объект.
Возможно, лучшая нотация строк, которую мы можем использовать в JavaScript — это JSON — JavaScript Object Notation. JSON — это легкий формат обмена данными, вдохновленный литеральной нотацией JavaScript, как показано выше. JSON поддерживается PHP и многими другими серверными языками (см. Json.org ).
В JavaScript есть два метода JSON:
- JSON.stringify ( obj ) — преобразует объект JavaScript в строку JSON
- JSON.parse ( str ) — преобразует строку JSON обратно в объект JavaScript
К сожалению, очень немногие браузеры предоставляют такие методы. На сегодняшний день только Firefox 3.5, Internet Explorer 8.0 и Chrome 3 beta предлагают встроенную поддержку. Некоторые библиотеки JavaScript предлагают свои собственные инструменты JSON (например, YUI ), но многие этого не делают (включая jQuery ).
Тем не менее, еще не все потеряно — JavaScript гибкий, и мы можем реализовывать JSON-методы stringify и parse всякий раз, когда браузер требует их.
В верхней части нашего кода мы создадим переменную JSON, которая указывает на собственный объект JSON или пустой объект, если он недоступен:
var JSON = JSON || {};
Код JSON.stringify немного сложнее:
// implement JSON.stringify serialization JSON.stringify = JSON.stringify || function (obj) { var t = typeof (obj); if (t != "object" || obj === null) { // simple data type if (t == "string") obj = '"'+obj+'"'; return String(obj); } else { // recurse array or object var n, v, json = [], arr = (obj && obj.constructor == Array); for (n in obj) { v = obj[n]; t = typeof(v); if (t == "string") v = '"'+v+'"'; else if (t == "object" && v !== null) v = JSON.stringify(v); json.push((arr ? "" : '"' + n + '":') + String(v)); } return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}"); } };
Если JSON.stringify недоступен, мы определяем новую функцию, которая принимает один параметр obj. Параметр может быть единственным значением, массивом или сложным объектом, таким как obj1 выше.
Код проверяет тип объекта. Отдельные значения возвращаются немедленно, и изменяются только строки, чтобы заключить в кавычки значение.
Если передан массив или объект, код перебирает все свойства:
- К значениям строк добавлены кавычки.
- Дочерние массивы или объекты рекурсивно передаются в функцию JSON.stringify.
- Результирующие значения добавляются в конец массива json [] в виде строки «name: value» или просто как одно значение для элементов массива.
- Наконец, массив json преобразуется в список, разделенный запятыми, и при необходимости возвращается в скобках array [] или object {}.
Если ваш мозг болит, вам будет приятно узнать, что код JSON.parse намного проще:
// implement JSON.parse de-serialization JSON.parse = JSON.parse || function (str) { if (str === "") str = '""'; eval("var p=" + str + ";"); return p; };
Это преобразует строку JSON в объект, используя eval ().
Прежде чем вы приступите к реализации функций сериализации JSON во всех ваших проектах, рассмотрим несколько ошибок:
- Этот код был намеренно сокращен. Это будет работать в большинстве ситуаций, но есть небольшие различия с нативными методами JSON.stringify и JSON.parse.
- Не каждый объект JavaScript поддерживается. Например, Date () вернет пустой объект, тогда как нативные методы JSON закодируют его в строку даты / времени.
- Код будет сериализовать функции, например, var obj1 = {myfunc: function (x) {}}; тогда как нативные методы JSON не будут.
- Очень большие объекты будут вызывать ошибки рекурсии.
- Использование eval () в JSON.parse по своей природе рискованно. Это не будет проблемой, если вы вызываете свои собственные веб-службы, но вызовы сторонних приложений могут случайно или намеренно сломать вашу страницу и вызвать проблемы с безопасностью. При необходимости более безопасный (но более длинный и медленный) парсер JavaScript доступен на json.org .
Я надеюсь, что вы найдете код полезным. Не стесняйтесь использовать его в своих проектах.
Ресурсные файлы:
- Демонстрационная страница сериализации JSON
- Полный код JavaScript (json-serialization.js)
- Скачать полный код в ZIP-файл
Связанное чтение:
Скоро: полезное приложение сериализации JSON…