Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including serializable-es5 with all npm packages installed. Try it out:

var serializableEs5 = require("serializable-es5")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

serializable-es5 v1.0.5

A serialization utility that automatically serialize and de-serialize Class instance.

serializable-es5

A serialization utility that automatically serialize and de-serialize Class instance. It makes saving and restoring process of modular application much easier.

NPM version Build Status Clean Code Dependency Status devDependency Status License

Browser support

Desktop: Chrome, Safari, Firefox, Opera, IE9+

Installation

    npm install serializable-es5

    or 

    jspm install npm:serializable-es5

Usage

An example :


    var Serializable = require('serializable-es5');


    /**
    * Assume we are developing a shopping website,
    * And we have a page contains a list of items
    * that a user is going to buy.
    */
    var Cart = function (domParent) {
        this._items  = [];          // Cart items.
        this._parent = domParent;

        this._buildUI();
    };

    /**
    * Property '_serializeInfo' must be provided because
    * Serializable utility recognize an object as serializable by 
    * checking the existence of this property.
    */
    Cart._serializeInfo = [
        '_items',           
        '_dataTable',
        '_nonExist',        // Non-exist property will be skipped during serialization.
        '_finalize'
    ];

    Cart.prototype = {
        constructor: Cart,

        /**
        * When this method is called, Serializable.serialize() will scan 
        * Cart._serializeInfo and if an element of this array is :
        *
        *   1. A property, then the value of this property will be simply returned (if 
        *      the value is of type String, Number, .etc), or be deep cloned then returned 
        *      (if the value is of type Object, Array, etc.)
        *   2. A function, then it will check whether this function name has prefix '_serialized' 
        *      , it will execute this function if it has, otherwise it will simply 
        *      skip it. ( Be noted that a function with no prefix '_serialized' will still be 
        *      executed during deserialization process. )
        *
        *   // The structure of return value of this method will be like this :
        *
        *   {
        *       _ : {
        *           className:    'Cart',
        *           purpose:      'save',           // By default is saving purpose.
        *           isSerialized: true
        *       },
        *
        *       info: {
        *           _items: Array,    // An array of item objects. ( is a deep-copied list.)
        *           
        *           // The value of _dataTable has the same structure as Cart instance's , 
        *           // Since DataTable Class also implemented _serializeInfo interface.
        *
        *           _dataTable:     {                   
        *                               _ : {
        *                                   className:    'DataTable',
        *                                   purpose:      'save',
        *                                   isSerialized: true
        *                               },
        *                               info: {
        *                                   _serializedAltRowColor: Boolean
        *                               }
        *                           }
        *       }
        *   };
        *
        */
        serialize: function () {
            /**
            * serialize() method takes two arguments :
            *   argument 1. it is usually the instance itself.
            *   argument 2. Class name in String.
            */
            return Serializable.serialize(this, 'Cart');
        },

        _buildUI: function () {
            /**
            * You can ignore this.
            */
            this._domContainer = $('<div>').appendTo(this._parent)
                                           .addClass('cart');
            this._header = $('<div>').appendTo(this._domContainer)
                                     .addClass('hdr')
                                     .text('My Cart');
            /**
            * Create DataTable instance.
            */
            this._dataTable = new DataTable(this._domContainer);
        },

        /**
        * Add an item to the list.
        */
        add: function (item) {
            this._items.push(item);
            this._loadList();          
            return this;
        },

        _loadList: function () {
            this._dataTable.load(this._items);  // Reload data table with new list.
        },

        /**
        * If user changed row-alternative-color settings.
        * Reload data table to reflect this change.
        *
        * You can ignore this method, just remember this setting is 
        * important to the users and we will save it.
        */
        altRowColor: function (enableAltRowColor) {
            if (typeof enableAltRowColor === 'boolean') {
                if (this._dataTable.altRowColor() !== enableAltRowColor) {
                    this._dataTable.altRowColor(enableAltRowColor);
                    this._loadList();
                }
            }
            else if (typeof enableAltRowColor !== 'undefined')
                throw "IllegalArgumentException: enableAltRowColor must be a Boolean.";

            return this;
        },

        /**
        * This method will only be called during deserialization.
        * This is useful after all data is restored from deserialization and 
        * you might want to do some last step operation, e.g. resize this 
        * instance, etc.
        *
        * ( A function which has a name with prefix '_serialized' will be 
        *   called during both serialization and deserialization, otherwise it 
        *   will only be called during deserialization. )
        */
        _finalize: function () {
            this._loadList();   // Items are already restored we reload the list.
            this._resize();     // Data list are loaded, you might want to resize.
        }
    };


    /**
    * DataTable class is incomplete, but since I am just showing 
    * the usage of Serializable utility, I am not going to complete 
    * this class.
    */
    var DataTable = function (domParent) {
        this._altRowColor = false;
    };

    DataTable._serializeInfo = [
        '_serializedAltRowColor'   
    ];                             

    DataTable.prototype = {
        constructor: DataTable,

        altRowColor: function (isAltRowColor) {
            if (typeof isAltRowColor === 'boolean')
                this._altRowColor = isAltRowColor;
            else 
                return this._altRowColor;
        },

        /**
        * Assume this method will load all data to doms and 
        * show it to user.
        */
        load: function (rows) {
        },

        /**
        * You don't need to call this method explicitly,
        * this method will be called when 'Serializable' utility recognizes that 
        * the value of Cart._dataTable is an instance of DataTable class which 
        * implemented serializable interface ( has '_serializeInfo' ).
        */
        serialize: function () {
            return Serializable.serialize(this, 'DataTable');
        },

        /**
        * This method will be called during both serialization and deserialization.
        */
        _serializedAltRowColor: function (serialized) {
            /**
            * Deserialization.
            */
            if (typeof serialized === 'boolean') {
                this._altRowColor = serialized;
                /**
                * You might add more code here.
                */
            }
            /**
            * serialization.
            */
            else {
                return this._altRowColor;
            }
        }
    };



    // Create Cart instance.
    var cart = new Cart(document.body);

    // Fake data.
    var getItem = function (name, price) {
        return {
            type: 'fruit',
            weight: '1kg',
            name: name,
            price: price
        };
    };

    // Assume we have a button.
    $('#btn-add-item').bind('click', function () {
        var item = getItem('apple', 30);
        cart.add(item);
    });

    cart.add( getItem('orange', 12) )
        .add( getItem('banana',  6) )
        .add( getItem('lemon',   8) );

    /**
    * Now you have a copy of serialized cart data,
    * you can save it to a database table or anywhere you want.
    */
    var dataToSave = JSON.stringify( cart.serialize() );

    /**
    * Restore data is as easy as serialization.
    * @return {Cart} - a Cart instance.
    */
    var cart = Serializable.deserialize( JSON.parse(dataFromDB) );

    /**
    * You can also provide a cart instance as the 2nd argument, 
    * but this is optional. If omitted, a cart instance will be 
    * created during deserialization and finally returned. If provided,
    * the same instance will be returned.
    */
    var cart = Serializable.deserialize( JSON.parse(dataFromDB), cartInstance );

Public properties and methods :

Tests

    npm test

Todo

  • [ ] Add the document of public interfaces :balloon:
  • [ ] Add test.
RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free