索引
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为空格缩进值,默认为2deserialize(json, rootParent, setId)反序列化,并将反序列化的对象加入DataModeljson:此参数可为JSON对象Object,也可为字符串化的JSON对象rootParent:如果反序列化的Data对象的parent为空,则调用data.setParent(rootParent)为其设置parentsetId:指定是否用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