如果我有一堆普通的旧对象,那么将它们映射到一堆类的最佳方法是什么?
例如,如果我使用HTTPService引入一些JSON,然后反序列化它,我会有一堆看起来像这样的对象:
{ type: "person",
id: 42,
name: "David" }
我想把它们变成Person类的实例:
class Person {
id:int;
name:String;
}
有没有一些标准的,一般的方法呢?
(还要考虑:如何处理对象之间的关系?例如,如果Person有一个额外的“配偶”字段:
{ type: "person", spouse: 61, ... } // Where 61 is the ID of the spouse
)
谢谢, 大卫
答案 0 :(得分:3)
没有标准的方法可以做到这一点,但你可以用两种不同的方式解决它。
版本1:构造方法
public class Person {
public function Person(raw:Object=null) {
if (raw != null) {
for ( var key:String in raw ) {
try {
this[key] = raw[key];
} catch (e:Error) {}
}
...
这有点容易出错。如果名为 key 的属性不存在,则分配将失败,如果类型不匹配或无法自动强制,它也将失败。
版本2:flash.utils.describeType()
更复杂,让您更有控制力。首先,您必须创建Person的实例并调用describeType()。
var o:Object = { ... } // raw person data
var p:Person = new Person();
var typeDesc:XML = flash.utils.describeType( p );
for (var key:String in o) {
var node:XML = typeDesc.variable.(@name==key)[0];
if ( node != null ) {
// Person class has a property *key*
p[key] = o[key];
}
}
但请注意使用getter和setter而不是公共变量。您无法使用typeDesc.variable访问它们,而是必须使用typeDesc.accessor并检查其访问属性是否不是writeonly。
关于您的类型键。要动态加载类,您可以执行以下操作:
var clazz:Class = flash.utils.getDefinitionByName(raw.type+"");
var person:Person = Person( new clazz() );
当然raw.type可能包含 Person 或 com.package.Person ,只要您的目标类存在并且正在使用项目编译或使用SWC动态加载
看看:
http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html#getDefinitionByName() 和http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html#describeType()
希望这会有所帮助:)
答案 1 :(得分:1)
为了保持干净并且不易出错,我会使用单独的对象来完成这两项任务。例如,要处理转换,您可能具有以下对象:
public class PersonFactory
{
function buildFromGenerics(objects:Array):Array
{
var a:Array = [];
var l:int = objects.length;
for (var i:int = 0; i < l; i++)
{
var o:Object = objects[i];
var p:Person = new Person();
p.id = o['id'];
p.name = o['name'];
a[i] = p
}
return a;
}
}
将此步骤的所有逻辑移动到一个单独的对象中允许您隔离此功能,该功能实际上与实际的Person对象无关,因此没有任何可用性。
对于第二种情况,我会使用一个单独的对象来保存所有Person对象,并提供一个用于检索它们的接口,如下所示:
public class PersonCollection
{
private var _people:Array;
public function setPeople(people:Array):void
{
_people = people;
}
public function getPersonByID(id:int):Person
{
var l:int = _people.length;
for (var i:int = 0; i < l; i++)
{
var p:Person = _people[i];
if (p.id == id)
{
return p;
}
}
return null;
}
}
这种分离有助于保持代码清洁,还提供了一种简单的方法来处理和管理代码。希望有所帮助。