在 Flex/ActionScript 開發中,將 Value Object (VO) 序列化為 JSON 是高頻需求。手動拼接 20+ 屬性不僅繁瑣難維護,還違反 DRY 原則。本文介紹如何利用 flash.utils.describeType() 實現運行時反射,自動獲取對象所有公共屬性並生成 JSON 字串。
describeType(obj:Object):XML 返回描述對象類型結構的 XML,包含類繼承關係、實現接口、存取器、常量、方法、參數、變量等完整元數據。
| 標籤 | 用途 | 關鍵屬性 |
|---|---|---|
<type> | 根節點 | name、base、isDynamic、isFinal、isStatic |
<variable> | 實例變量 (var) | name、type |
<accessor> | 存取器 (get/set) | name、access、type、declaredBy |
<method> | 方法 | name、returnType、declaredBy |
<factory> | 靜態成員容器 | 僅當 isStatic=true 時出現 |
/**
* 生成對象屬性-值對應的 JSON 字串
* @param obj 目標對象,null 返回空串
* @return JSON 字串,格式 {"prop":"value",...}
* 注意:[Bindable] 標記的屬性無法獲取
*/
public static function getOneJsonObject(obj:Object):String {
if (obj == null) return "";
var jsonInfo:String = "{";
// 反射獲取所有 variable 標籤(實例變量)
var properties:XMLList = describeType(obj).variable;
for each (var propertyInfo:XML in properties) {
var propertyName:String = propertyInfo.@name;
// 直接通過括號語法動態訪問屬性值
jsonInfo += '"' + propertyName + '":"' + obj[propertyName] + '",';
}
// 移除尾部逗號並閉合
if (jsonInfo.length > 1) {
jsonInfo = jsonInfo.substring(0, jsonInfo.length - 1);
}
jsonInfo += "}";
return jsonInfo;
}
for each (var item:XML in xmlList) 是 E4X 標準遍歷方式propertyInfo.@name 獲取 XML 屬性值obj[propertyName] 利用 AS3 動態特性讀取屬性值[Bindable] 元數據編譯器生成的隱式存取器不會出現在 variable 列表中,需改用 accessor 标籤獲取// 獲取所有方法(含繼承)
var methods:XMLList = describeType(obj).method;
// 獲取存取器(含 Bindable 屬性)
var accessors:XMLList = describeType(obj).accessor;
// 獲取繼承鏈
var extendsClass:XMLList = describeType(obj).extendsClass;
// 獲取實現接口
var interfaces:XMLList = describeType(obj).implementsInterface;
describeType 較重,同一類型多次調用建議緩存 XML 結果obj[propertyName] 返回 Object,複雜類型需自行處理序列化as3corelib 的 JSON.encode() 或 Gson 風格庫,支援註解驅動、日期格式化等高級特性describeType 是 ActionScript 反射的核心入口,通過解析其返回的 XML 結構,可實現對象自動序列化、動態表單生成、運行時類型檢查等進階功能。雖然 Flex 已逐漸退出歷史舞台,但其反射設計思想對理解動態語言運行時元編程仍有參考價值。