索引
HT for Web
对数据模型ht.DataModel
提供了ht.JSONSerializer
的序列化功能,
可将DataModel
中包含的Data
对象以及属性序列化为JSON格式,
同时提供反序列化构建DataModel
数据对象的功能。本手册将详细介绍HT for Web
的基本类定义规则,ht.JSONSerializer
类的基本使用,
以及自定义类和属性的序列化和反序列化案例。
JavaScript
语言未提供严谨的面对对象类的语言级支持,为此HT
设计了一套类封装体系供用户选择采用。
定义和使用com.hightopo.Person
类的步骤如下:
1、定义包目录结构
// define package
com = {};
com.hightopo = {};
2、定义类构造函数
// define Person class constructor
com.hightopo.Person = function(firstName, lastName){
com.hightopo.Person.superClass.constructor.call(this);
this.setFirstName(firstName);
this.setLastName(lastName);
};
3、定义类属性和函数
// define Person class properties and methods
ht.Default.def('com.hightopo.Person', Object, {
_firstName: null,
_lastName: null,
getFirstName: function(){
return this._firstName;
},
setFirstName: function(firstName){
this._firstName = firstName;
},
getLastName: function(){
return this._lastName;
},
setLastName: function(lastName){
this._lastName = lastName;
},
getDescription: function(){
return 'firstName:' + this._firstName + ' lastName:' + this._lastName;
}
});
4、构建对象和函数调用
var person = new com.hightopo.Person('eric', 'lin');
console.log('FirstName - ' + person.getFirstName());
console.log('LastName - ' + person.getLastName());
console.log('Description - ' + person.getDescription());
5、输出结果
FirstName - eric
LastName - lin
Description - firstName:eric lastName:lin
定义和使用com.hightopo.Person
的子类com.hightopo.Student
的步骤如下:
1、定义类构造函数
// define Student class constructor
com.hightopo.Student = function(firstName, lastName, grade){
com.hightopo.Student.superClass.constructor.call(this, firstName, lastName);
this.setGrade(grade);
};
2、定义类属性和函数
// define Student class properties and methods
ht.Default.def('com.hightopo.Student', com.hightopo.Person, {
_grade: null,
getGrade: function(){
return this._grade;
},
setGrade: function(grade){
this._grade = grade;
},
// override getDescription method
getDescription: function(){
var desc = com.hightopo.Student.superClass.getDescription.call(this);
return desc + ' grade:' + this._grade;
}
});
3、构建对象和函数调用
var student = new com.hightopo.Student('ben', 'lin', 2);
console.log('FirstName - ' + student.getFirstName());
console.log('LastName - ' + student.getLastName());
console.log('Grade - ' + student.getGrade());
console.log('Description - ' + student.getDescription());
4、输出结果
FirstName - ben
LastName - lin
Grade - 2
Description - firstName:ben lastName:lin grade:2
ht.JSONSerializer
可对DataModel
数据模型的Data
数据对象以及DataModel
自身的attr
属性,
进行JSON
格式的序列化和反序列化,默认会HT
所有预定义类的get/set
属性,style
和attr
属性进行序列化,
JSONSerializer
类的函数如下:
toJSON()
函数返回序列化的JSON
对象serialize(space)
返回序列化后JSON
对象的字符串内容,space
为空格缩进值,默认为2
deserialize(json, rootParent, setId)
反序列化,并将反序列化的对象加入DataModel
json
:此参数可为JSON
对象Object
,也可为字符串化的JSON
对象rootParent
:如果反序列化的Data
对象的parent
为空,则调用data.setParent(rootParent)
为其设置parent
setId
:指定是否用JSON
的i
信息作为Data
的id
属性,默认为false
由Data
构造函数自动生成id
isSerializable(data)
函数默认返回true
代表序列化所有对象,重载该函数可自定义data
是否参与序列化getProperties(data)
函数返回Object
类型的map
对象,key
为要序列化的get/set
属性getStyles(data)
函数返回Object
类型的map
对象,key
为要序列化的style
属性getAttrs(data)
函数返回Object
类型的map
对象,key
为要序列化的attr
属性字符串化的
JSON
参数常出现因换行信息导致解析出错,对于这种情况可通过json.replace(/\n/g,"")
对字符串参数做预处理
以下为get/set
、style
和attr
属性是否序列化相关函数的默认实现逻辑,可重载自定义,默认实现皆调用了Data
对象的相应函数,
因此也可以通过重载Data
对象类型的实现改变逻辑。
ht.JSONSerializer
默认逻辑:
getProperties: function(data){
return data.getSerializableProperties();
},
getStyles: function(data){
return data.getSerializableStyles();
},
getAttrs: function(data){
return data.getSerializableAttrs();
},
ht.Data
默认逻辑:
getSerializableProperties: function(){
return {
name: 1,
displayName: 1,
icon: 1,
toolTip: 1,
parent: 1,
layer: 1,
tag: 1,
adjustChildrenToTop: 1
};
},
getSerializableStyles: function(){
var name, map = {};
for (name in this._styleMap) {
map[name] = 1;
}
return map;
},
getSerializableAttrs: function(){
var name, map = {};
for (name in this._attrObject) {
map[name] = 1;
}
return map;
}
ht.Edge
默认逻辑:
getSerializableProperties: function(){
var map = ht.Edge.superClass.getSerializableProperties.call(this);
addMethod(map, {
source: 1,
target: 1
});
return map;
}
以下代码为DataModel
类封装的便捷函数,如果不需要自定义序列化逻辑,直接操作DataModel
的序列化相关函数即可。
serialize: function(space){
return (new ht.JSONSerializer(this)).serialize(space);
},
toJSON: function(){
return (new ht.JSONSerializer(this)).toJSON();
},
deserialize: function (json, rootParent, setId) {
(new ht.JSONSerializer(this)).deserialize(json, rootParent, setId);
}
以下例子构建了MyData
的继承于ht.Data
的子类,重载了getSerializableProperties
函数,增加了对age
属性的存储,
重载了getSerializableAttrs
函数,仅对attr2
属性进行存储,通过var jsonString = dataModel.serialize();
序列化
和dataModel.deserialize(jsonString)
反序列化之后,attr1
丢失外,其他属性皆恢复原始值。
例子代码如下:
// define package
com = {};
com.hightopo = {};
// define MyData
var MyData = com.hightopo.MyData = function(age, attr1, attr2){
MyData.superClass.constructor.call(this);
this.setAge(age);
this.setAttr('attr1', attr1);
this.setAttr('attr2', attr2);
};
ht.Default.def('com.hightopo.MyData', ht.Data, {
_age: 1,
getAge: function(){
return this._age;
},
setAge: function(age){
if(age !== this._age){
var oldValue = this._age;
this._age = age;
this.firePropertyChange('age', oldValue, age);
}
},
getSerializableProperties: function(){
var map = MyData.superClass.getSerializableProperties.call(this);
map.age = true;
return map;
},
getSerializableAttrs: function(){
return {
attr2: 1
};
}
});
var dataModel = new ht.DataModel();
dataModel.setAttr('website', 'www.hightopo.com');
var data = new MyData(34, 'tw', 'ht');
data.setTag('20130301');
dataModel.add(data);
var jsonString = dataModel.serialize();
console.log(jsonString);
dataModel.clear();
dataModel.setAttr('website', null);
dataModel.deserialize(jsonString);
data = dataModel.getDataByTag('20130301');
console.log(data.getAge());
console.log(data.getAttr('attr1'));
console.log(data.getAttr('attr2'));
console.log(dataModel.getAttr('website'));
运行结果如下:
{
"v": "2.8",
"d": [
{
"c": "com.hightopo.MyData",
"i": 3,
"p": {
"tag": "20130301",
"age": 34
},
"a": {
"attr2": "ht"
}
}
],
"a": {
"website": "www.hightopo.com"
}
}
34
undefined
ht
www.hightopo.com