This question has come up a lot on FlexCoders recently, so I wanted to offer to the community a generic solution to convert plain old vanilla objects into full-fledged class instances.
I had originally developed this solution to be used with the JSON library that I made for the Adobe Labs Corelib project, but it's really an all-purpose solution. Essentially, my utility method allows you to turn any remote service that returns plain old ActionScript objects (like JSON, WebServices, etc) into a service that returns typed class instances, much like RemoteObject.
This makes it easier to employ the ValueObject pattern... instead of getting back an object with some properties attached, I can convert that object into, say, a Book ValueObject. The Book then is easier to work with because I get IDE and compiler support from strong typing, and it also speeds up the code execution since accessing values in typed objects executes faster than in non-typed objects.
You can download my ObjectTranslator, and its test cases, here. (MIT License)
Usage is as follows:
import com.darronschall.examples.vo.Book;
import com.darronschall.serialization.ObjectTranslator;
// Define an object with properties that mimic the variable names
// inside of the Book class
var bookObj:Object = { title: "My Book title", pageCount: 10, inLibrary: true };
// Convert the generic object into an instance of the Book class
var book:Book = ObjectTranslator.objectToInstance( bookObj, Book ) as Book;
Yup, it's really that simple.
Unfortunately, things get a little more complicated when you have nested ValueObjects. I didn't take the time to make my method recursive, so it's up to you to first convert the nested objects into instances, and then convert the top level object into an instance. It's a little more work that can avoided by some recursion. I've outlined what the algorithm would look like inside of the code, I just haven't had the time to write it yet.
import com.darronschall.examples.vo.Book;
import com.darronschall.examples.vo.Student;
import com.darronschall.serialization.ObjectTranslator;
var studentObj:Object = { firstName: "test first",
lastName: "test last",
favoriteBook: { title: "Favorite Book!" }
};
// First we need to convert the nested objects to classes
studentObj.favoriteBook = ObjectTranslator.objectToInstance( studentObj.favoriteBook, Book );
// Convert the student object to a Student class
var student:Student = ObjectTranslator.objectToInstance( studentObj, Student ) as Student;
So, to summarize, the objectToInstance method allows JSON and WebService services to return true class instances from the server, making them behave like RemoteObject and allowing developers to more easily employ the ValueObject pattern. Use the objectToInstance method on the object that the service returns, and then use the converted instance elsewhere in your code.
Those who are curious about the implementation will get a kick out of the simplicity of my algorithm. Essentially, all I'm doing is constructing an AMF packet with the class name and the object property values, then doing a byteArray.readObject() to convert the AMF packet into a class instance. The code is fairly well commented so you can follow along easily. I'd like to think this is one of those "so simple it's brilliant" type of moments...
Have fun, and let me know if you run into any issues!
Tags: Flex 2, ActionScript 3, JSON

