Skip to content

Instantly share code, notes, and snippets.

@wolever
Created July 29, 2010 20:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wolever/499129 to your computer and use it in GitHub Desktop.
Save wolever/499129 to your computer and use it in GitHub Desktop.
package serialization {
import flash.utils.ByteArray;
import utils.logger.Log;
/**
* Serializes 'obj'. If serialization fails, tries really hard to figure
* out what caused it to fail.
*/
public function safeSerialize(obj:*):ByteArray {
var serialized:ByteArray = new ByteArray();
try {
serialized.writeObject(obj);
} catch (e:*) {
if (e.errorID == 2004) {
Log.error("A 'parameter is invalid' error is raised when " +
"serializing an instance of a class which isn't " +
"tagged with [RemoteClass] but has a parent which " +
"is tagged with [RemoteClass].");
Log.error(findInvalidField(obj));
throw Error("safeSerialize: serialization failed. Check log for " +
"diagnostic messages.");
} else {
throw e;
}
}
serialized.position = 0;
return serialized;
}
}
import flash.utils.ByteArray;
import flash.utils.getQualifiedClassName;
import org.hamcrest.DiagnosingMatcher;
import flash.utils.Dictionary;
import mx.utils.ObjectUtil;
import utils.objKeys;
/**
* When 'obj' is an instance which can't be serialized, try to figure
* out which field is causing problems.
*/
function findInvalidField(obj:*, chain:Array=null, seen:Dictionary=null):String {
if (chain == null)
chain = [];
if (seen == null)
seen = new Dictionary();
// Objects we have seen - we know these can't be serialized
seen[obj] = true;
// Get the version of the object which the serializer will see, then
// iterate over its fields, trying to find the field which can't
// be serialized.
var field:String;
var data:Object = obj;
for (field in data) {
// We can ignore values we know to be bad.
if (data[field] in seen)
continue;
if (!canSerialize(data[field]))
return findInvalidField(data[field], chain.concat(field), seen);
}
// If all of the fields of the object can be serailized, it means one
// of two things:
// - This object can't be serialized
// - The object is hiding a reference to something that can't be
// serialized.
var msg:String;
var type:String = getQualifiedClassName(obj);
var chainStr:String = chain.join(".");
msg = "Field '" + chainStr + "' of the serialized object could not " +
"be serialized.\n" +
"It is of type: " + type + "\n" +
"NB: It's likely that this object is fine, and it's " +
"some child instance that is causing the problems.\n" +
"The other instances which could not be serialized are:\n" +
" " + objKeys(seen).join("\n ") + "\n" +
"(note: this is only a guess - it may be incorrect)";
return msg;
}
/**
* Can 'obj' be serialized?
* Will do the right thing if 'obj' is an instance of Serializable.
*/
function canSerialize(obj:*):Boolean {
var b:ByteArray = new ByteArray();
var err:*;
try {
b.writeObject(obj);
return true;
} catch (e:*) {
err = e;
}
// This is the error we get when we can't serialize something
if (err is ArgumentError && err.errorID == 2004)
return false;
// Otherwise, re-throw the error
throw err;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment