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: 911.815 // 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]; } |
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.
Hi your function looks great but it does not work for me in FF 3.5 .. i get always the error:
1 2 3 | 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!
@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...
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):
1 | 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";}} |
@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...
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.
@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
This function is giving me some troubles, throwing error : "Function utf8_decode() does not exists --- Line ... 120"
Original code :
1 2 3 4 56 7 8 9 10 | case 's': (...) // Length was calculated on an utf-8 encoded string // so wait with decodingreaddata = this.utf8_decode(readdata); break; case 'a': (...) |
I changed to :
1 2 3 4 56 7 8 9 10 | case 's': (...) // Length was calculated on an utf-8 encoded string // so wait with decodingreaddata = 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.
@ Frank: Thanks for voicing your opinion : )
We're no designers. How do you like the new comment-code colors?
@ 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!
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).
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:
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 | 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
@ 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
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.
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!?
1
2
3
4
56
7
8
| var test = { a: "Martin", b: "Schmidt", c: "äöüß", d: "&&%%$$" }; var x = serialize(test); var test2 = unserialize(x); |
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:
1 | return _unserialize(data, 0)[2]; |
to
1 | return _unserialize(String(data), 0)[2]; |
Regarding this code:
1 2 | 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.
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...
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
1 2 | var testArray=unserialize(someStuff); alert(testArray.length); |
with no luck
Bye Thomas
@ 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?
Unserialize function is not working for Javascript Objects can u tell me something related with this.....
@ Jakub: Thanks for contributing to our project. When I implement your change and test it, I get the following error from rhino:
[CODE="text"]
kevin@trinity:~/workspace/plutonia-phpjs/_tools$ ./phpjstest.php unserialize
Exception in thread "Thread-0" 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(<adapter>)
at java.lang.Thread.run(Thread.java:619)
[/CODE]
Hi,
I have noticed that for some strings, this 'for' should be executed 'length -1' not 'length' times:
1 2 3 4 | for(var i = 0;i < length;i++){ var chr = data.slice(offset + (i - 1),offset + i); buf.push(chr); } |
when I have changed it to:
1 2 3 4 | for(var i = 0;i < length-1;i++){ var chr = data.slice(offset + (i - 1),offset + i); buf.push(chr); } |
it has worked well.
BTW. You are doing a great job here.
@ 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 & 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.
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!
:-(
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:
1 2 3 | for (key in objprops[0]) { objout += "" + key + "=objprops[0]['" + key + "'];"; } |
Fixed code:
1 2 3 | for (key in objprops[0]) { objout += "this['" + key + "']=objprops[0]['" + key + "'];"; } |
dptr1988
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']
######################
@ 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 & unserialize are two functions that do just that, and I wouldn't be surprised if this is faster then generating & parsing XML. Which is a pretty heavy format actually.
Best in most cases would probably be JSON though. Because since PHP5, PHP can
[CODE="PHP"]
$json = json_encode($array);
[/CODE]
And JavaScript can interpret JSON natively:
1 2 | for ( item in json ) { } |
JSON will also produce the smallest output compared to XML & serialized arrays.
For safe transportation you may want to additionally:
[CODE="PHP"]
base = base64_encode(json_encode($data));
[/CODE]
1 | data = base64_decode(base); |
base64 functions have also been ported in this project.
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
@ 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.
You have:
1 | if (inp == "" || inp.length < 2) { |
Isn't the string length of "" < 2 anyway?
How about:
1 | if (inp.length < 2) { |
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 "0" or "1" 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:
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 158 159 160161 162 163 164 165166 | 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 == "" || inp.length < 2) { errormsg = "input is too short"; return; } var val, kret, vret, cval; var type = inp.charAt(0); var cont = inp.substring(2); var size = 0, divpos = 0, endcont = 0, rest = "", next = ""; switch (type) { case "N": // null if (inp.charAt(1) != ";") { errormsg = "missing ; for null"; } // leave val undefined rest = cont; break; case "b": // boolean if (!/[01];/.test(cont.substring(0,2))) { errormsg = "value not 0 or 1, or missing ; for boolean"; } val = (cont.charAt(0) == "1"); rest = cont.substring(2); //changed... break; case "s": // string val = ""; divpos = cont.indexOf(":"); if (divpos == -1) { errormsg = "missing : for string"; break; } size = parseInt(cont.substring(0, divpos)); if (size == 0) { if (cont.length - divpos < 4) { errormsg = "string is too short"; break; } rest = cont.substring(divpos + 4); break; } if ((cont.length - divpos - size) < 4) { errormsg = "string is too short"; break; } if (cont.substring(divpos + 2 + size, divpos + 4 + size) != "\";") { errormsg = "string is too long, or missing \";"; } val = cont.substring(divpos + 2, divpos + 2 + size); rest = cont.substring(divpos + 4 + size); break; case "i": // integer case "d": // float var dotfound = 0; for (var t = 0; t < cont.length; t++) { cval = cont.charAt(t); if (isNaN(parseInt(cval)) && !(type == "d" && cval == "." && !dotfound++)) { endcont = t; break; } } if (!endcont || cont.charAt(endcont) != ";") { errormsg = "missing or invalid value, or missing ; for int/float"; } val = cont.substring(0, endcont); val = (type == "i" ? parseInt(val) : parseFloat(val)); rest = cont.substring(endcont + 1); break; case "a": // array if (cont.length < 4) { errormsg = "array is too short"; return; } divpos = cont.indexOf(":", 1); if (divpos == -1) { errormsg = "missing : for array"; return; } size = parseInt(cont.substring(1*divpos, 0)); //changed... cont = cont.substring(divpos + 2); val = new Array(); if (cont.length < 1) { errormsg = "array is too short"; return; } for (var i = 0; i + 1 < size * 2; i += 2) { kret = unserialize(cont, 1); if (error || kret[0] == undefined || kret[1] == "") { errormsg = "missing or invalid key, or missing value for array"; return; } vret = unserialize(kret[1], 1); if (error) { errormsg = "invalid value for array"; return; } val[kret[0]] = vret[0]; cont = vret[1]; } if (cont.charAt(0) != "}") { errormsg = "missing ending }, or too many values for array"; return; } rest = cont.substring(1); break; case "O": // object divpos = cont.indexOf(":"); if (divpos == -1) { errormsg = "missing : for object"; 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) != "\":") { errormsg = "object name is too long, or missing \":"; return; } var objprops = unserialize("a:" + cont.substring(divpos + 4 + size), 1); if (error) { errormsg = "invalid object properties"; return; } rest = objprops[1]; var objout = "function " + objname + "(){"; for (key in objprops[0]) { objout += "" + key + "=objprops[0]['" + key + "'];"; } objout += "}val=new " + objname + "();"; eval(objout); break; default: errormsg = "invalid input type"; } return (arguments.length == 1 ? val : [val, rest]);} |
Pedro Tainha - email@pedrotainha.com
www.pedrotainha.com (in construction)


Brett Zamir
Feb 19th
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.
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.