[转]JavaScript 版本的 PHP serialize/unserialize 完整实现

转载 2006年06月07日 23:15:00


本文来自于:http://www.coolcode.cn/?p=171
作者:Ma Bingyao


以前写 PHPRPC 实现时,JavaScript 版本的序列化实现是修改自 http://www.devpro.it/code/102.html 的,这个实现虽然目前仍然在更新,不过它并没有完全实现 PHP 序列化的所有标记,因此它无法序列化复杂对象,例如嵌套对象,也无法反序列化所有的 PHP 序列化以后的内容。因此我重新编写了一个实现,这个实现与 PHP 5 的序列化完全兼容,并且可以反序列化 PHP 4、PHP 5 和 PHP 6 序列化的内容。支持魔术方法 __sleep 和 __wakeup,支持实现了 Serializable 接口的序列化和反序列化(在 JavaScript 没有接口的概念,因此只要对象中包含 serialize 和 unserialize 方法就可以了,关于 Serializable 接口与自定义序列化的更多内容请参见:PHP 序列化(serialize)格式详解——自定义对象序列化)。该实现兼容以下版本的浏览器(已测试):

//IE 4+(包括 Windows Vista 的 IE 7+ 与 Windows Mobile 2003/Windows Moblie 5 的 IE 4)
//Mozilla/Firefox
//Opera(包括 Opera Mini 和 Opera Mobile,但对于 Opera Mobile 8.5 beta 2 for Windows Mobile 5 Pocket PC 对象序列化时,对象名的序列化支持的不完整,而其他版本都正常。)
//Konqueror
//Safari
//Epiphany
//其他浏览器未测试,但应该基本上只要支持 JavaScript 的浏览器都可以支持(有条件的用户希望能够帮忙测试)。

本程序中需要调用 utf.js 中的 utf16to8 和 utf8to16 这两个函数来进行字节流与 JavaScript 字符串之间的转换。

下载: phpserializer.js

/* phpserializer.js - JavaScript to PHP serialize / unserialize class.

* This class is designed to convert php variables to javascript
* and javascript variables to php with a php serialize unserialize
* compatible way.
*
* Copyright (C) 2006 Ma Bingyao <
andot@ujn.edu.cn>
* Version: 3.0c
* LastModified: Jun 2, 2006
* This library is free.  You can redistribute it and/or modify it.
*
http://www.coolcode.cn/?p=171
*/
 
function serialize(o) {
    var p = 0, sb = [], ht = [], hv = 1;
    function classname(o) {
        if (typeof(o) == "undefined" || typeof(o.constructor) == "undefined") return '';
        var c = o.constructor.toString();
        c = utf16to8(c.substr(0, c.indexOf('(')).replace(/(^/s*function/s*)|(/s*$)/ig, ''));
        return ((c == '') ? 'Object' : c);
    }
    function is_int(n) {
        var s = n.toString(), l = s.length;
        if (l > 11) return false;
        for (var i = (s.charAt(0) == '-') ? 1 : 0; i < l; i++) {
            switch (s.charAt(i)) {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': break;
                default : return false;
            }
        }
        return !(n < -2147483648 || n > 2147483647);
    }
    function in_ht(o) {
        for (k in ht) if (ht[k] === o) return k;
        return false;
    }
    function ser_null() {
        sb[p++] = 'N;';
    }
    function ser_boolean(b) {
        sb[p++] = (b ? 'b:1;' : 'b:0;');
    }
    function ser_integer(i) {
        sb[p++] = 'i:' + i + ';';
    }
    function ser_double(d) {
        if (d == Number.POSITIVE_INFINITY) d = 'INF';
        else if (d == Number.NEGATIVE_INFINITY) d = '-INF';
        sb[p++] = 'd:' + d + ';';
    }
    function ser_string(s) {
        var utf8 = utf16to8(s);
        sb[p++] = 's:' + utf8.length + ':"';
        sb[p++] = utf8;
        sb[p++] = '";';
    }
    function ser_array(a) {
        sb[p++] = 'a:';
        var lp = p;
        sb[p++] = 0;
        sb[p++] = ':{';
        for (var k in a) {
            if (typeof(a[k]) != 'function') {
                is_int(k) ? ser_integer(k) : ser_string(k);
                __serialize(a[k]);
                sb[lp]++;
            }
        }
        sb[p++] = '}';
    }
    function ser_object(o) {
        var cn = classname(o);
        if (cn == '') ser_null();
        else if (typeof(o.serialize) != 'function') {
            sb[p++] = 'O:' + cn.length + ':"';
            sb[p++] = cn;
            sb[p++] = '":';
            var lp = p;
            sb[p++] = 0;
            sb[p++] = ':{';
            if (typeof(o.__sleep) == 'function') {
                var a = o.__sleep();
                for (var kk in a) {
                    ser_string(a[kk]);
                    __serialize(o[a[kk]]);
                    sb[lp]++;
                }
            }
            else {
                for (var k in o) {
                    if (typeof(o[k]) != 'function') {
                        ser_string(k);
                        __serialize(o[k]);
                        sb[lp]++;
                    }
                }
            }
            sb[p++] = '}';
        }
        else {
            var cs = o.serialize();
            sb[p++] = 'C:' + cn.length + ':"';
            sb[p++] = cn;
            sb[p++] = '":' + cs.length + ':{';
            sb[p++] = cs;
            sb[p++] = "}";
        }
    }
    function ser_pointref(R) {
        sb[p++] = "R:" + R + ";";
    }
    function ser_ref(r) {
        sb[p++] = "r:" + r + ";";
    }
    function __serialize(o) {
        if (o == null || o.constructor == Function) {
            hv++;
            ser_null();
        }
        else switch (o.constructor) {
            case Boolean: {
                hv++;
                ser_boolean(o);
                break;
            }
            case Number: {
                hv++;
                is_int(o) ? ser_integer(o) : ser_double(o);
                break;
            }
            case String: {
                hv++;
                ser_string(o);
                break;
            }
            case Array: {
                var r = in_ht(o);
                if (r) {
                    ser_pointref(r);
                }
                else {
                    ht[hv++] = o;
                    ser_array(o);
                }
                break;
            }
            default: {
                var r = in_ht(o);
                if (r) {
                    hv++;
                    ser_ref(r);
                }
                else {
                    ht[hv++] = o;
                    ser_object(o);
                }
                break;
            }
        }
    }
    __serialize(o);
    return sb.join('');
}
 
function unserialize(ss) {
    var p = 0, ht = [], hv = 1; r = null;
    function unser_null() {
        p++;
        return null;
    }
    function unser_boolean() {
        p++;
        var b = (ss.charAt(p++) == '1');
        p++;
        return b;
    }
    function unser_integer() {
        p++;
        var i = parseInt(ss.substring(p, p = ss.indexOf(';', p)));
        p++;
        return i;
    }
    function unser_double() {
        p++;
        var d = ss.substring(p, p = ss.indexOf(';', p));
        switch (d) {
            case 'INF': d = Number.POSITIVE_INFINITY; break;
            case '-INF': d = Number.NEGATIVE_INFINITY; break;
            default: d = parseFloat(d);
        }
        p++;
        return d;
    }
    function unser_string() {
        p++;
        var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));
        p += 2;
        var s = utf8to16(ss.substring(p, p += l));
        p += 2;
        return s;
    }
    function unser_array() {
        p++;
        var n = parseInt(ss.substring(p, p = ss.indexOf(':', p)));
        p += 2;
        var a = [];
        ht[hv++] = a;
        for (var i = 0; i < n; i++) {
            var k;
            switch (ss.charAt(p++)) {
                case 'i': k = unser_integer(); break;
                case 's': k = unser_string(); break;
                case 'U': k = unser_unicode_string(); break;
                default: return false;
            }
            a[k] = __unserialize();
        }
        p++;
        return a;
    }
    function unser_object() {
        p++;
        var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));
        p += 2;
        var cn = utf8to16(ss.substring(p, p += l));
        p += 2;
        var n = parseInt(ss.substring(p, p = ss.indexOf(':', p)));
        p += 2;
        if (eval(['typeof(', cn, ') == "undefined"'].join(''))) {
            eval(['function ', cn, '(){}'].join(''));
        }
        var o = eval(['new ', cn, '()'].join(''));
        ht[hv++] = o;
        for (var i = 0; i < n; i++) {
            var k;
            switch (ss.charAt(p++)) {
                case 's': k = unser_string(); break;
                case 'U': k = unser_unicode_string(); break;
                default: return false;
            }
            if (k.charAt(0) == '/0') {
                k = k.substring(k.indexOf('/0', 1) + 1, k.length);
            }
            o[k] = __unserialize();
        }
        p++;
        if (typeof(o.__wakeup) == 'function') o.__wakeup();
        return o;
    }
    function unser_custom_object() {
        p++;
        var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));
        p += 2;
        var cn = utf8to16(ss.substring(p, p += l));
        p += 2;
        var n = parseInt(ss.substring(p, p = ss.indexOf(':', p)));
        p += 2;
        if (eval(['typeof(', cn, ') == "undefined"'].join(''))) {
            eval(['function ', cn, '(){}'].join(''));
        }
        var o = eval(['new ', cn, '()'].join(''));
        ht[hv++] = o;
        if (typeof(o.unserialize) != 'function') p += n;
        else o.unserialize(ss.substring(p, p += n));
        p++;
        return o;
    }
    function unser_unicode_string() {
        p++;
        var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));
        p += 2;
        var sb = [];
        for (i = 0; i < l; i++) {
            if ((sb[i] = ss.charAt(p++)) == '//') {
                sb[i] = String.fromCharCode(parseInt(ss.substring(p, p += 4), 16));
            }
        }
        p += 2;
        return sb.join('');
    }
    function unser_ref() {
        p++;
        var r = parseInt(ss.substring(p, p = ss.indexOf(';', p)));
        p++;
        return ht[r];
    }
    function __unserialize() {
        switch (ss.charAt(p++)) {
            case 'N': return ht[hv++] = unser_null();
            case 'b': return ht[hv++] = unser_boolean();
            case 'i': return ht[hv++] = unser_integer();
            case 'd': return ht[hv++] = unser_double();
            case 's': return ht[hv++] = unser_string();
            case 'U': return ht[hv++] = unser_unicode_string();
            case 'r': return ht[hv++] = unser_ref();
            case 'a': return unser_array();
            case 'O': return unser_object();
            case 'C': return unser_custom_object();
            case 'R': return unser_ref();
            default: return false;
        }
    }
    return __unserialize();
}

测试页面:http://test.coolcode.cn/phpserializer

 

php函数unserialize数据返回false问题分析

unserialize的这个问题是由一个emlog论坛用户在使用时报错而发现的 问题表现情况如下: emlog缓存的保存方式是将php的数据对象(数组)序列化(serialize)后以文件...
  • farcall
  • farcall
  • 2014年10月05日 14:12
  • 1326

php unserialize 返回false的解决方法

php 提供serialize(序列化) 与 unserialize(反序列化)方法。 使用serialize序列化后,再使用unserialize反序列化就可以获取原来的数据。...
  • fdipzone
  • fdipzone
  • 2014年07月23日 21:48
  • 26175

ThinkPHP系统变量,常量,序列化,反序列化,缓存

变量的输出: 在模板中输出一个变量有两种形式:{$list.name} {$list[‘name’]} 在模板中可以使用系统变量,以$Think.开头    系统变量:(举例选几个)    获...
  • W1365966490
  • W1365966490
  • 2013年05月29日 20:08
  • 4683

PHP序列化反序列化serialize和unserialize函数

昨天网上看到一道面试题,如下: “类的属性可以序列化后保存到session中,从而以后可以恢复整个类,这要用到的函数是?” 我记得原来老师说过序列化函数是"serialize",查了下,果不其然,今天...
  • forLightWay
  • forLightWay
  • 2016年02月21日 10:42
  • 14854

PHP多种序列化/反序列化的方法serialize和unserialize函数

序列化是将变量转换为可保存或传输的字符串的过程;反序列化就是在适当的时候把这个字符串再转化成原来的变量使用。这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性。 1. serialize和...
  • u014254803
  • u014254803
  • 2016年07月04日 14:00
  • 319

php serialize & unserialize

两者在php手册上的解释是: serialize — Generates a storable representation of a value serialize — 产生一个可存储的值的表示...
  • aigoleague
  • aigoleague
  • 2012年08月24日 21:38
  • 590

unserialize的这个问题是由一个emlog论坛用户在使用时报错而发现的 问题表现情况如下: emlog缓存的保存方式是将php的数据对象(数组)序列化(serialize)后以文件的形式存放,

unserialize的这个问题是由一个emlog论坛用户在使用时报错而发现的 问题表现情况如下: emlog缓存的保存方式是将php的数据对象(数组)序列化(serialize)后以文件...
  • farcall
  • farcall
  • 2014年10月05日 14:09
  • 623

php函数 序列化serialize() 与 反序列化unserialize()

手册的描述: serialize (PHP 4, PHP 5, PHP 7) serialize — 产生一个可存储的值的表示 描述  string seri...
  • h330531987
  • h330531987
  • 2017年04月22日 00:09
  • 584

非常好用的两个PHP函数 serialize()和unserialize()

//serialize.php //声明一个类 class dog {     var $name;     var $age;     var $owner;     function ...
  • autumn20080101
  • autumn20080101
  • 2016年09月21日 15:52
  • 82

php函数serialize()与unserialize()

本文转自:http://zxianf.blog.163.com/blog/static/30120701201072443623381/ php函数serialize()与unserialize...
  • mybluesky1983
  • mybluesky1983
  • 2011年08月31日 17:11
  • 456
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[转]JavaScript 版本的 PHP serialize/unserialize 完整实现
举报原因:
原因补充:

(最多只允许输入30个字)