Use PHP functions in JavaScript

JavaScript unserialize

Takes a string representation of variable and recreates it

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
42
43
44
4546
47
48
49
5051
52
53
54
5556
57
58
59
6061
62
63
64
6566
67
68
69
7071
72
73
74
7576
77
78
79
8081
82
83
84
8586
87
88
89
9091
92
93
94
9596
97
98
99
100101
102
103
104
105106
107
108
109
110111
112
113
114
115116
117
118
119
120121
122
123
124
125126
127
128
129
130131
132
133
134
135136
137
138
139
140141
142
143
144
145146
147
148
149
150151
152
153
154
155156
157
function unserialize (data) {
    // Takes a string representation of variable and recreates it  
    // 
    // version: 1008.1718
    // discuss at: http://phpjs.org/functions/unserialize    // +     original by: Arpad Ray (mailto:arpad@php.net)
    // +     improved by: Pedro Tainha (http://www.pedrotainha.com)
    // +     bugfixed by: dptr1988
    // +      revised by: d3x
    // +     improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)    // +        input by: Brett Zamir (http://brett-zamir.me)
    // +     improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: Chris
    // +     improved by: James
    // +        input by: Martin (http://www.erlenwiese.de/)    // +     bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: Le Torbi
    // +     input by: kilops
    // +     bugfixed by: Brett Zamir (http://brett-zamir.me)
    // -      depends on: utf8_decode    // %            note: We feel the main purpose of this function should be to ease the transport of data between php & js
    // %            note: Aiming for PHP-compatibility, we have to translate objects to arrays
    // *       example 1: unserialize('a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}');
    // *       returns 1: ['Kevin', 'van', 'Zonneveld']
    // *       example 2: unserialize('a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}');    // *       returns 2: {firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}
    var that = this;
    var utf8Overhead = function(chr) {
        // http://phpjs.org/functions/unserialize:571#comment_95906
        var code = chr.charCodeAt(0);        if (code < 0x0080) {
            return 0;
        }
        if (code < 0x0800) {
             return 1;        }
        return 2;
    };
 
     var error = function (type, msg, filename, line){throw new that.window[type](msg, filename, line);};
    var read_until = function (data, offset, stopchr){
        var buf = [];
        var chr = data.slice(offset, offset + 1);
        var i = 2;        while (chr != stopchr) {
            if ((i+offset) > data.length) {
                error('Error', 'Invalid');
            }
            buf.push(chr);            chr = data.slice(offset + (i - 1),offset + i);
            i += 1;
        }
        return [buf.length, buf.join('')];
    };    var read_chrs = function (data, offset, length){
        var buf;
 
        buf = [];
        for (var i = 0;i < length;i++){            var chr = data.slice(offset + (i - 1),offset + i);
            buf.push(chr);
            length -= utf8Overhead(chr); 
        }
        return [buf.length, buf.join('')];    };
    var _unserialize = function (data, offset){
        var readdata;
        var readData;
        var chrs = 0;        var ccount;
        var stringlength;
        var keyandchrs;
        var keys;
         if (!offset) {offset = 0;}
        var dtype = (data.slice(offset, offset + 1)).toLowerCase();
 
        var dataoffset = offset + 2;
        var typeconvert = function(x) {return x;}; 
        switch (dtype){
            case 'i':
                typeconvert = function (x) {return parseInt(x, 10);};
                readData = read_until(data, dataoffset, ';');                chrs = readData[0];
                readdata = readData[1];
                dataoffset += chrs + 1;
            break;
            case 'b':                typeconvert = function (x) {return parseInt(x, 10) !== 0;};
                readData = read_until(data, dataoffset, ';');
                chrs = readData[0];
                readdata = readData[1];
                dataoffset += chrs + 1;            break;
            case 'd':
                typeconvert = function (x) {return parseFloat(x);};
                readData = read_until(data, dataoffset, ';');
                chrs = readData[0];                readdata = readData[1];
                dataoffset += chrs + 1;
            break;
            case 'n':
                readdata = null;            break;
            case 's':
                ccount = read_until(data, dataoffset, ':');
                chrs = ccount[0];
                stringlength = ccount[1];                dataoffset += chrs + 2;
 
                readData = read_chrs(data, dataoffset+1, parseInt(stringlength, 10));
                chrs = readData[0];
                readdata = readData[1];                dataoffset += chrs + 2;
                if (chrs != parseInt(stringlength, 10) && chrs != readdata.length){
                    error('SyntaxError', 'String length mismatch');
                }
                 // Length was calculated on an utf-8 encoded string
                // so wait with decoding
                readdata = that.utf8_decode(readdata);
            break;
            case 'a':                readdata = {};
 
                keyandchrs = read_until(data, dataoffset, ':');
                chrs = keyandchrs[0];
                keys = keyandchrs[1];                dataoffset += chrs + 2;
 
                for (var i = 0; i < parseInt(keys, 10); i++){
                    var kprops = _unserialize(data, dataoffset);
                    var kchrs = kprops[1];                    var key = kprops[2];
                    dataoffset += kchrs;
 
                    var vprops = _unserialize(data, dataoffset);
                    var vchrs = vprops[1];                    var value = vprops[2];
                    dataoffset += vchrs;
 
                    readdata[key] = value;
                } 
                dataoffset += 1;
            break;
            default:
                error('SyntaxError', 'Unknown / Unhandled data type(s): ' + dtype);            break;
        }
        return [dtype, dataoffset - offset, typeconvert(readdata)];
    };
        return _unserialize((data+''), 0)[2];
}
external links: original PHP docs | raw js source

Examples

» Example 1

Running

1
unserialize('a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}');

Should return

1
['Kevin', 'van', 'Zonneveld']

» Example 2

Running

1
unserialize('a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}');

Should return

1
{firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}

Dependencies

In order to use this function, you also need:

Open syntax issues

php.js uses JsLint to help us keep our code consistent and prevent some common bugs.

Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.


Authors

Thanks to the following developers, you get to have unserialize goodness in JavaScript.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
Thériault
May 4th Permalink

q  @mscdex: I don't think PHP sessions can be unserialized in PHP itself. The format a PHP session is stored in (the one you provided) differs from the format serialize($_SESSION) would return, which is what you need to use. However, after looking at the code above for the unserialize function, I don't see a case statement for "O," so you're right that this function won't work with objects.

Gravatar
mscdex
May 4th Permalink

q  I'm having the same problem as Alind (this function doesn't seem to support PHP objects). I am attempting to unserialize a PHP session, but the session string starts with:

breadCrumbs|O:15:"BreadCrumbStack":3:{s:22:" BreadCrumbStack stack";a:2:{i:0;a:6:{s:7:"item_id"; ......



What happens as a result of unserializing this string is that the function sees the first 'b' in 'breadCrumbs' and thinks it found a boolean value, which causes unserialize() to return a value of true in this case.

Is there a (already existing) fix for this?

Gravatar
Brett Zamir
Feb 19th Permalink

q  @plotas: It looks as though you are trying to use it within an XPCOM component. Is that right? If so, as with also JavaScript code modules (see https://developer.mozilla.org/en/JavaScript_code_modules ), certain JavaScript environments do not automatically include a window object.

So, you can either pass in a window object to the component at some point to initialize the window used by the component (esp. if you need a particular window, though that is not important in this case), or you may be able to simply use this to define "window". It is possible that just using "window" could cause errors (I believe I've tried to redefine "alert" in that context and couldn't use it either), in such case, just rename "window", but hopefully you won't have to do that.

If your code that is using unserialize() is on an object/class you'll need to ensure "window" is defined as a property of the object; otherwise, it can be defined globally within the component.

this.window = Components.classes['@mozilla.org/appshell/appShellService;1'].getService(Components.interfaces.nsIAppShellService).hiddenDOMWindow;



I believe there is another way to get a window in such code too, but the above works for me.

Note that in regular client-side JS, "this.window" will translate to "window.window" which conveniently for us, simply refers back to the window object. Same effect I believe in XPCOM and code modules.

Depending on your needs, if you weren't aware, Firefox also includes the JSON (see https://developer.mozilla.org/en/JSON , though maybe you need nsIJSON for XPCOM code: https://developer.mozilla.org/en/nsIJSON ) for object serialization.

Gravatar
plotas
Feb 19th Permalink

q  Hi your function looks great but it does not work for me in FF 3.5 .. i get always the error:

Error: that.window[type] is not a constructor
Source File: file:///E:/Dienste/FirefoxPortable/Data/profile/extensions/%7Be4a8a97b-f2ed-450b-b12d-ee082ba24781%7D/components/greasemonkey.js
Line: 1305


well maybe that is because try to use in greasemonkey? any idea? Thaanks!

Gravatar
Brett Zamir
7 Nov '09 Permalink

q  @Lyle Pratt: By altering the error message to return the offset, it seems that the function is running into problems where you have a space at the end of a string (i.e., after "107 West Denison Drive") if that helps you or someone else to debug this. Not sure if the space is being dropped somewhere or something...

Gravatar
Lyle Pratt
4 Nov '09 Permalink

q  Hello,

I am having some serious problems using this script in all versions of IE.

The error is getting thrown at line 146 (from the code excerpt on this page). It seems that that switch statement is getting defaulted a few times and its throwing off the whole unserialization.

Can someone take a look at this? Im in a pretty big bind at the moment.

Here is a sample of what I am trying to unserialize that is failing (works in Chrome, safari, and FF):

a:18:{s:10:"fa_essay_1";a:4:{s:7:"storage";s:16:"Essay Question 1";s:5:"value";s:8:"testfest";s:2:"id";s:10:"fa_essay_1";s:5:"group";s:10:"fa_essay_1";}s:10:"fa_essay_2";a:4:{s:7:"storage";s:16:"Essay Question 2";s:5:"value";s:16:"unset_this_value";s:2:"id";s:10:"fa_essay_2";s:5:"group";s:10:"fa_essay_2";}s:15:"form_first_name";a:4:{s:7:"storage";s:10:"First Name";s:5:"value";s:7:"Bobby J";s:2:"id";s:15:"form_first_name";s:5:"group";s:15:"form_first_name";}s:16:"form_middle_name";a:4:{s:7:"storage";s:11:"Middle Name";s:5:"value";s:2:"P.";s:2:"id";s:16:"form_middle_name";s:5:"group";s:16:"form_middle_name";}s:14:"form_last_name";a:4:{s:7:"storage";s:9:"Last Name";s:5:"value";s:6:"Baylor";s:2:"id";s:14:"form_last_name";s:5:"group";s:14:"form_last_name";}s:19:"form_preferred_name";a:4:{s:7:"storage";s:14:"Preferred Name";s:5:"value";s:5:"Bubba";s:2:"id";s:19:"form_preferred_name";s:5:"group";s:19:"form_preferred_name";}s:13:"form_birthday";a:4:{s:7:"storage";s:8:"Birthday";s:5:"value";s:9:"12-JUN-62";s:2:"id";s:13:"form_birthday";s:5:"group";s:13:"form_birthday";}s:11:"form_gender";a:4:{s:7:"storage";s:6:"Gender";s:5:"value";s:1:"M";s:2:"id";s:11:"form_gender";s:5:"group";s:11:"form_gender";}s:12:"form_country";a:4:{s:7:"storage";s:7:"Country";s:5:"value";s:13:"United States";s:2:"id";s:12:"form_country";s:5:"group";s:12:"form_country";}s:12:"form_address";a:4:{s:7:"storage";s:7:"Address";s:5:"value";s:24:"107 West Denison Drive ";s:2:"id";s:12:"form_address";s:5:"group";s:12:"form_address";}s:10:"form_phone";a:4:{s:7:"storage";s:12:"Phone Number";s:5:"value";s:16:"unset_this_value";s:2:"id";s:10:"form_phone";s:5:"group";s:10:"form_phone";}s:10:"form_email";a:4:{s:7:"storage";s:5:"Email";s:5:"value";s:34:"Bobby_Baylor-University@baylor.edu";s:2:"id";s:10:"form_email";s:5:"group";s:10:"form_email";}s:10:"form_major";a:4:{s:7:"storage";s:5:"Major";s:5:"value";s:10:"Accounting";s:2:"id";s:10:"form_major";s:5:"group";s:10:"form_major";}s:19:"form_classification";a:4:{s:7:"storage";s:14:"Classification";s:5:"value";s:8:"Freshman";s:2:"id";s:19:"form_classification";s:5:"group";s:19:"form_classification";}s:16:"fa_art_interests";a:4:{s:7:"storage";s:13:"Art Interests";s:5:"value";s:8:"testfest";s:2:"id";s:16:"fa_art_interests";s:5:"group";s:16:"fa_art_interests";}s:17:"fa_film_interests";a:4:{s:7:"storage";s:32:"Film and Digital Media Interests";s:5:"value";s:16:"unset_this_value";s:2:"id";s:17:"fa_film_interests";s:5:"group";s:17:"fa_film_interests";}s:18:"fa_music_interests";a:4:{s:7:"storage";s:15:"Music Interests";s:5:"value";s:16:"unset_this_value";s:2:"id";s:18:"fa_music_interests";s:5:"group";s:18:"fa_music_interests";}s:20:"fa_theatre_interests";a:4:{s:7:"storage";s:22:"Theatre Arts Interests";s:5:"value";s:16:"unset_this_value";s:2:"id";s:20:"fa_theatre_interests";s:5:"group";s:20:"fa_theatre_interests";}}



Gravatar
Brett Zamir
4 Nov '09 Permalink

q  @kilops, our pleasure. Kevin set up a good pattern of crediting people I think, and indeed pointing out bugs should get credit since it is the first step in fixing them! Also thanks for the positive feedback and for keeping your eye out for any other bugs...

Gravatar
kilops
3 Nov '09 Permalink

q  Thanx "Brett Zamir" for the explanation.

And thx again for crediting me the fix despite I only came with the bug and a bad workaround.

If I see something else like that i'll keep you in touch.


ps: hurray for PHP.JS and everyone making it.

Gravatar
Brett Zamir
3 Nov '09 Permalink

q  @kilops: Fixed at http://github.com/kvz/phpjs/commit/ce785027aeff2a1461ff54d5fd44d35b2f2d68d7 . When we made function calls use 'this', I may have overlooked a few nested function cases where we have to declare "that" (or something) outside of the nested functions and then refer to "that" inside the nested functions (since "this" has a different meaning depending on the function it is in and how it is used).

In this case (no pun intended), since "this" in a non-instantiated function refers to the global window object, and since you were using the namespaced version, it wasn't finding the method in the global namespace (as it shouldn't unless you redeclared it there). Using the "that" convention lets us drop through the "that" variable to the inner function so it can have access to the "this" on the enclosing method. Hope that makes sense.

If not, see http://www.crockford.com/javascript/private.html

Gravatar
kilops
3 Nov '09 Permalink

q  This function is giving me some troubles, throwing error : "Function utf8_decode() does not exists --- Line ... 120"

Original code :

case 's':
(...)

// Length was calculated on an utf-8 encoded string
// so wait with decoding
readdata = this.utf8_decode(readdata);

break;
case 'a':
(...)




I changed to :

case 's':
(...)

// Length was calculated on an utf-8 encoded string
// so wait with decoding
readdata = PHP_JS.prototype.utf8_decode(readdata);

break;
case 'a':
(...)




I don't really know why but using "PHP_JS.prototype." instead of "this." fix my problem (despite the fact it's supposed to be the same object as far as I know)


FYI :
I'm using the namespaced version on FF 3.5.3
and the serialize function may have the same problem.

Gravatar
Kevin van Zonneveld
8 Oct '09 Permalink

q  @ Frank: Thanks for voicing your opinion : )
We're no designers. How do you like the new comment-code colors?

Gravatar
Kevin van Zonneveld
8 Oct '09 Permalink

q  @ Le Torbi: Wow big kuddos to you! I must say I would have never thought of that. Thanks a lot Le Torbi!

We will include this in the official repo. It will be online shortly. Thanks again!

Gravatar
Frank
8 Oct '09 Permalink

q  This black background is horrible and makes it a pain to read this site!

Gravatar
Le Torbi
26 Sep '09 Permalink

q  Whoops, I guess my bug is another than the one discussed below my post.

The problem is (or was) that strings, which contain special chars (like German umlauts or Japanese), have some additional chars after they have been unserialized. For example 's:6:"höhö":s:3:"abc"' became 'höhö":' and 'abc' (": was added to the string with the umlauts).

However, the code I've postetd below fixes this issue.

PS: ö is one character (German umlaut oe) not two (just in case it'll be screwed up when posted).

Gravatar
Le Torbi
26 Sep '09 Permalink

q  Hi guys,

I just fixed the utf8 issue. The problem was, that the given size represents the length in bytes, but it was interpreted as if it is the length in characters. I fixed it by calculating the size in bytes of each character and reducing the length accordingly. Here is the code:

var read_chrs = function (data, offset, length){
    var buf;

    buf = [];
    for (var i = 0;i < length;i++){
        var chr = data.slice(offset + (i - 1),offset + i);
        buf.push(chr);
        length -= utf8Overhead(chr); // NEW LINE
    }
    return [buf.length, buf.join('')];
};
var utf8Overhead = function(char) { // NEW FUNCTION
    var code = char.charCodeAt(0);
    if (code < 0x0080)
        return 0;
    if (code < 0x0800)
         return 1;
    return 2;
};



I've also written a faster method to calculate the string length in bytes for the serialize() function. See my posting there for details.

BTW: What do I have to to to get this into the official code?

Bai
Le Torbi

Gravatar
Kevin van Zonneveld
4 Sep '09 Permalink

q  @ Martin: Good point. The base64 encoding function have utf8 dependencies too, so we might as well add them to the serialize functions.

Added to our new git rep:
http://github.com/kvz/phpjs/commit/80ef918e43ffe015c241cb31d35b3afafada7d33

Gravatar
Martin
24 Aug '09 Permalink

q  In opposite to the php unserialize function this one cannot handle utf8 strings. If you call utf8_encode() before you call unserialize() and run the returned data through utf8_decode(), it works fine. But to have the same functionality as the php function, this should be part of the unserialize function.

Gravatar
Martin
23 Aug '09 Permalink

q  This does not work with german umlauts (ö, ä, ü, ß).

I get the following message:

Unknown / Unhandled data type(s):

I'm wondering, why there is a call of "encodeURIComponent" in the serialize function but no "decodeURIComponent" in the unserialize function. Maybe it has something to do with this!?

   var test = {
    a: "Martin",
    b: "Schmidt",
    c: "äöüß",
    d: "&&%%$$" };

  var x = serialize(test);
  var test2 = unserialize(x);

Gravatar
fer
16 Jul '09 Permalink

q  thanks

does not work well with accents such as: á

Gravatar
k_de surya
7 Jul '09 Permalink

q  thanks for the code...

Gravatar
Kevin van Zonneveld
3 Jul '09 Permalink

q  @ Chris + James: Thanks for your fixes guys, I've added them to SVN

Gravatar
James
29 Jun '09 Permalink

q  Had a problem using this on FF 3.5b4. The browser was having trouble at determining what data was so I had to make the following change:

return _unserialize(data, 0)[2];



to

return _unserialize(String(data), 0)[2];

Gravatar
Chris
26 Jun '09 Permalink

q  Regarding this code:

            case 'b':
                typeconvert = function (x) {return parseInt(x, 10) == 1;};


I don't know that this could ever matter, but it should technically be `return parseInt(x, 10) != 0` because all non-zero values are true.

Gravatar
Brett Zamir
3 Apr '09 Permalink

q  Hi Thomas,

In PHP.JS, we return objects often where arrays are used in PHP. This is because JavaScript has no other way to represent associative-arrays--arrays in which the indexes are either not all numerical, or are not numbered sequentially from 0 and/or by 1..

Here's the link to count() as Kevin pointed out: http://phpjs.org/functions/view/count/ which does counting of objects too...

Gravatar
Kevin van Zonneveld
3 Apr '09 Permalink

q  Why not use count :)

Gravatar
Thomas Buschhardt
2 Apr '09 Permalink

q  Hallo, thanx for the code. How can I read the length of the list you returned in Example 1? Is this an array?
I try

var testArray=unserialize(someStuff);
alert(testArray.length);


with no luck

Bye Thomas

Gravatar
Kevin van Zonneveld
17 Dec '08 Permalink

q  @ Alind: It would really help if you could supply the exact code that fails so we can take a look at it, fix it, and add it as testcase to it stays fixed in the future as well. Would that be possible?

Gravatar
Alind
17 Dec '08 Permalink

q  Unserialize function is not working for Javascript Objects can u tell me something related with this.....

Gravatar
Kate
17 Sep '08 Permalink

q  Thank you so much for allowing me the opportunity to visit this site.

Gravatar
Kevin van Zonneveld
13 Sep '08 Permalink

q  @ Jakub: Thanks for contributing to our project. When I implement your change and test it, I get the following error from rhino:

[CODE=&quot;text&quot;]
kevin@trinity:~/workspace/plutonia-phpjs/_tools$ ./phpjstest.php unserialize
Exception in thread &quot;Thread-0&quot; org.mozilla.javascript.JavaScriptException: [object Error] (/home/kevin/workspace/plutonia-phpjs/functions/var/unserialize.js#16)
at org.mozilla.javascript.gen.c4._c2(Unknown Source)
at org.mozilla.javascript.gen.c4.call(Unknown Source)
at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:97)
at org.mozilla.javascript.gen.c4._c5(Unknown Source)
at org.mozilla.javascript.gen.c4.call(Unknown Source)
at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:97)
at org.mozilla.javascript.gen.c4._c5(Unknown Source)
at org.mozilla.javascript.gen.c4.call(Unknown Source)
at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:97)
at org.mozilla.javascript.gen.c4._c1(Unknown Source)
at org.mozilla.javascript.gen.c4.call(Unknown Source)
at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:97)
at org.mozilla.javascript.gen.c1._c1(Unknown Source)
at org.mozilla.javascript.gen.c1.call(Unknown Source)
at org.mozilla.javascript.ScriptRuntime.applyOrCall(ScriptRuntime.java:2234)
at org.mozilla.javascript.BaseFunction.execIdCall(BaseFunction.java:257)
at org.mozilla.javascript.IdFunctionObject.call(IdFunctionObject.java:127)
at org.mozilla.javascript.optimizer.OptRuntime.call2(OptRuntime.java:76)
at org.mozilla.javascript.gen.c2._c17(Unknown Source)
at org.mozilla.javascript.gen.c2.call(Unknown Source)
at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:66)
at org.mozilla.javascript.gen.c2._c4(Unknown Source)
at org.mozilla.javascript.gen.c2.call(Unknown Source)
at org.mozilla.javascript.optimizer.OptRuntime.callProp0(OptRuntime.java:119)
at org.mozilla.javascript.gen.c2._c107(Unknown Source)
at org.mozilla.javascript.gen.c2.call(Unknown Source)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:393)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:2834)
at org.mozilla.javascript.gen.c2.call(Unknown Source)
at org.mozilla.javascript.Context.call(Context.java:548)
at org.mozilla.javascript.JavaAdapter.callMethod(JavaAdapter.java:507)
at adapter1.run(&lt;adapter&gt;)
at java.lang.Thread.run(Thread.java:619)
[/CODE]

Gravatar
Jakub
11 Sep '08 Permalink

q  Hi,
I have noticed that for some strings, this 'for' should be executed 'length -1' not 'length' times:
[CODE=&quot;Javascript&quot;]
for(var i = 0;i &lt; length;i++){
var chr = data.slice(offset + (i - 1),offset + i);
buf.push(chr);
}
[/CODE]
when I have changed it to:
[CODE=&quot;Javascript&quot;]
for(var i = 0;i &lt; length-1;i++){
var chr = data.slice(offset + (i - 1),offset + i);
buf.push(chr);
}
[/CODE]
it has worked well.

BTW. You are doing a great job here.

Gravatar
Kevin van Zonneveld
27 Aug '08 Permalink

q  @ nimbus: This has been caused by a logic-mistake. JavaScript distincts associative arrays from objects. PHP does not. I've made some adjustments to correct the behaviour &amp; increase compatibility with PHP.

And for as testing the functions, I've just finished writing a CLI script that can now test functions from the commandline, so expect the quality to be higher in the near future.

Of course, input (ideas for tests, improvements) by readers is very much appreciated.

Gravatar
nimbus
28 Jul '08 Permalink

q  serializing arrays has two major flaws:

a) non-numeric indexes cause the function to break!

b) negative values break your function!

did you test your code at all?!

please fix or at least tell people - it took me quite a while to find that out!
:-(

Gravatar
Kevin van Zonneveld
22 Jul '08 Permalink

q  @ dptr1988: I've committed your fix and credited you accordingly. Thank you very much dptr1988!!

Gravatar
Bug when key names have spaces
22 Jul '08 Permalink

q  I have really enjoyed using these php.js functions. They sure make it easy for a PHP developer to use JavaScript

I have been using unserialize() on Firefox 3.0 and noticed that if the key name contains spaces they are not unserialized correctly. Down near the end of the function, right before it eval()'s the code, replace this code with the following:

Buggy code:
[CODE='Javascript']
for (key in objprops[0]) {
objout += &quot;&quot; + key + &quot;=objprops[0]['&quot; + key + &quot;'];&quot;;
}[/CODE]

Fixed code:
[CODE='Javascript']
for (key in objprops[0]) {
objout += &quot;this['&quot; + key + &quot;']=objprops[0]['&quot; + key + &quot;'];&quot;;
}[/CODE]

dptr1988

Gravatar
Kevin van Zonneveld
17 Jul '08 Permalink

q  @ Lukasz: Can you post me the serializedObject so we can test it?

Gravatar
Lukasz
27 Jun '08 Permalink

q  You have race conditions in your code
for the unserialize. That is you have return statement on multiple lines which sometimes but not always causes the an error

Example:
######################
var deserializedArray = unserialize(serializedObject);

var x = deserializedArray['someFiled'];

######################

Sometimes if I want to use the field ['someField'] of the deserializedArray immediately on the next line of code after calling the function unserialize I get the error saying that deserializedArray['someFiled'] has no properites. This is caused beacuse YOU HAVE RETUNED FROM THE FUNCTION BEFORE YOU HAVE FINISHED DESERIALIZING ALL THE FIELDS, AND THE CODE CONTINUES. I guess it is the way you used recursion that is the problem.

The actual output from Firebug:
######################
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserialize() finished ::
unserializeResp has no properties
[Break on this error] var anonsArr = unserializeResp['anons_media']
######################

Gravatar
Kevin van Zonneveld
28 Apr '08 Permalink

q  @ alberto: Of course there are many ways to transport data between server- and clientside.

Which way is better depends on your situation. In this project however it's all about mimicking PHP functionality. And serialize &amp; unserialize are two functions that do just that, and I wouldn't be surprised if this is faster then generating &amp; parsing XML. Which is a pretty heavy format actually.
Best in most cases would probably be JSON though. Because since PHP5, PHP can
[CODE=&quot;PHP&quot;]
$json = json_encode($array);
[/CODE]
And JavaScript can interpret JSON natively:
[CODE=&quot;Javascript&quot;]
for ( item in json ) {
}
[/CODE]
JSON will also produce the smallest output compared to XML &amp; serialized arrays.

For safe transportation you may want to additionally:

[CODE=&quot;PHP&quot;]
base = base64_encode(json_encode($data));
[/CODE]

[CODE=&quot;Javascript&quot;]
data = base64_decode(base);
[/CODE]

base64 functions have also been ported in this project.

Gravatar
alberto
27 Apr '08 Permalink

q  wouldn't it be better just to transform the php object data to an XML object that is easy to hang by Javascript?
Anybody interested in this way email me albertomelchor@hotmail.com

Gravatar
Kevin van Zonneveld
3 Apr '08 Permalink

q  @ Devin: Logically you're right but my guess is that Arpad Ray had performance on his mind when writing it like that.

It's a recursive function so every bit of performance tweaking will help.

I think the first check may be less CPU intensive than the second one. Though the second one probably needs to be in place for arrays and other cases, it is skipped if the first condition is true, thus saving you a calculation.

If you have other thoughts on that please let me know.

Gravatar
Devin
3 Apr '08 Permalink

q  You have:
[CODE=&quot;Javascript&quot;]
if (inp == &quot;&quot; || inp.length &lt; 2) {
[/CODE]

Isn't the string length of &quot;&quot; &lt; 2 anyway?
How about:
[CODE=&quot;Javascript&quot;]
if (inp.length &lt; 2) {
[/CODE]

Gravatar
Kevin van Zonneveld
20 Mar '08 Permalink

q  @ Pedro Tainha: Awesome! Thanks for the kind words and improved code!

Gravatar
Pedro Tainha
20 Mar '08 Permalink

q  Hello!!!

I was searching for this function in javascript a long time ago and happy to finally fond it. But when I tryed didn´t work with me.
I sent an email for the author but he didn´t reply (probably he had no time - no problem), so i had to learn the code and find the problems.
I´m glad because i solved my problem and at the same time, because i never tryed to contribute with something, this was inspiring and i can see that probably anyone can do it as well - Don´t be shy, try it!!!

(please don´t look at the language errors, I´m from Portugal and I don´t write with much frequency)

Now let´s get with the real stuff, that in reality isn´t so much.

the lines that were changed and comented with: '//changed...'

1. In the array case, the code was only prepared for the number of fields less then 10, now suports any number of fields

2. In the boolean case, the semicolon afther the &quot;0&quot; or &quot;1&quot; boolean variables wasn´t cuted.


Thanks very much to Arpad Ray, you did a great job. This function is very useful for me!!!
And will be for others, i will try to put a great toturial about this function and php using AJAX.
I prefer this instead Json to receive data from php.


The code is above:

[CODE=&quot;Javascript&quot;]

function unserialize ( inp ) {
// http://kevin.vanzonneveld.net
// + original by: Arpad Ray (mailto:arpad@php.net)
// * example 1: unserialize();
// * returns 1: ['Kevin', 'van', 'Zonneveld']
//
//*******************************************************************************
//
// * Reviewed at: 19/03/2008
// + by: Pedro Tainha (email@pedrotainha.com or pedrotainha@gmail.com)
//
// Notes:
// Fixed bugs for the cases: 'b'(boolean) and 'a'(array)
//
//*******************************************************************************


error = 0;
if (inp == &quot;&quot; || inp.length &lt; 2) {
errormsg = &quot;input is too short&quot;;
return;
}
var val, kret, vret, cval;
var type = inp.charAt(0);
var cont = inp.substring(2);
var size = 0, divpos = 0, endcont = 0, rest = &quot;&quot;, next = &quot;&quot;;

switch (type) {
case &quot;N&quot;: // null
if (inp.charAt(1) != &quot;;&quot;) {
errormsg = &quot;missing ; for null&quot;;
}
// leave val undefined
rest = cont;
break;
case &quot;b&quot;: // boolean
if (!/[01];/.test(cont.substring(0,2))) {
errormsg = &quot;value not 0 or 1, or missing ; for boolean&quot;;
}
val = (cont.charAt(0) == &quot;1&quot;);
rest = cont.substring(2); //changed...
break;
case &quot;s&quot;: // string
val = &quot;&quot;;
divpos = cont.indexOf(&quot;:&quot;);
if (divpos == -1) {
errormsg = &quot;missing : for string&quot;;
break;
}
size = parseInt(cont.substring(0, divpos));
if (size == 0) {
if (cont.length - divpos &lt; 4) {
errormsg = &quot;string is too short&quot;;
break;
}
rest = cont.substring(divpos + 4);
break;
}
if ((cont.length - divpos - size) &lt; 4) {
errormsg = &quot;string is too short&quot;;
break;
}
if (cont.substring(divpos + 2 + size, divpos + 4 + size) != &quot;\&quot;;&quot;) {
errormsg = &quot;string is too long, or missing \&quot;;&quot;;
}
val = cont.substring(divpos + 2, divpos + 2 + size);
rest = cont.substring(divpos + 4 + size);
break;
case &quot;i&quot;: // integer
case &quot;d&quot;: // float

var dotfound = 0;
for (var t = 0; t &lt; cont.length; t++) {
cval = cont.charAt(t);
if (isNaN(parseInt(cval)) &amp;&amp; !(type == &quot;d&quot; &amp;&amp; cval == &quot;.&quot; &amp;&amp; !dotfound++)) {
endcont = t;
break;
}
}
if (!endcont || cont.charAt(endcont) != &quot;;&quot;) {
errormsg = &quot;missing or invalid value, or missing ; for int/float&quot;;
}
val = cont.substring(0, endcont);
val = (type == &quot;i&quot; ? parseInt(val) : parseFloat(val));
rest = cont.substring(endcont + 1);
break;
case &quot;a&quot;: // array
if (cont.length &lt; 4) {
errormsg = &quot;array is too short&quot;;
return;
}
divpos = cont.indexOf(&quot;:&quot;, 1);

if (divpos == -1) {
errormsg = &quot;missing : for array&quot;;
return;
}
size = parseInt(cont.substring(1*divpos, 0)); //changed...

cont = cont.substring(divpos + 2);
val = new Array();
if (cont.length &lt; 1) {
errormsg = &quot;array is too short&quot;;
return;
}
for (var i = 0; i + 1 &lt; size * 2; i += 2) {


kret = unserialize(cont, 1);

if (error || kret[0] == undefined || kret[1] == &quot;&quot;) {
errormsg = &quot;missing or invalid key, or missing value for array&quot;;
return;
}

vret = unserialize(kret[1], 1);

if (error) {
errormsg = &quot;invalid value for array&quot;;
return;
}
val[kret[0]] = vret[0];
cont = vret[1];
}

if (cont.charAt(0) != &quot;}&quot;) {
errormsg = &quot;missing ending }, or too many values for array&quot;;
return;
}

rest = cont.substring(1);
break;
case &quot;O&quot;: // object
divpos = cont.indexOf(&quot;:&quot;);
if (divpos == -1) {
errormsg = &quot;missing : for object&quot;;
return;
}
size = parseInt(cont.substring(0, divpos));
var objname = cont.substring(divpos + 2, divpos + 2 + size);
if (cont.substring(divpos + 2 + size, divpos + 4 + size) != &quot;\&quot;:&quot;) {
errormsg = &quot;object name is too long, or missing \&quot;:&quot;;
return;
}

var objprops = unserialize(&quot;a:&quot; + cont.substring(divpos + 4 + size), 1);

if (error) {
errormsg = &quot;invalid object properties&quot;;
return;
}
rest = objprops[1];

var objout = &quot;function &quot; + objname + &quot;(){&quot;;
for (key in objprops[0]) {
objout += &quot;&quot; + key + &quot;=objprops[0]['&quot; + key + &quot;'];&quot;;
}
objout += &quot;}val=new &quot; + objname + &quot;();&quot;;
eval(objout);
break;
default:
errormsg = &quot;invalid input type&quot;;
}

return (arguments.length == 1 ? val : [val, rest]);
}
[/CODE]


Pedro Tainha - email@pedrotainha.com

www.pedrotainha.com (in construction)


Contribute a New function

More functions

In this category

doubleval
empty
floatval
get_defined_vars
get_resource_type
gettype
import_request_variables
intval
is_array
is_binary
is_bool
is_buffer
is_callable
is_double
is_float
is_int
is_integer
is_long
is_null
is_numeric
is_object
is_real
is_resource
is_scalar
is_string
is_unicode
isset
print_r
serialize
settype
strval
» unserialize
var_dump
var_export

Support us

spread the word:


Use any PHP function in JavaScript


These kind folks have already donated: @HalfWinter, Paulo Freitas, Andros Peña Romo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>

Click here to lend your support to: phpjs and make a donation at www.pledgie.com !