(暂时还未完成整个文档)
基于html5 Canvas的DataMap定义工具,使用图形化的方式定义从“源数据”到“目标数据”的转换规则。
一.新建DataMap
1.定义源数据和目标数据格式
在列表页面点击“新建”按钮,在如下对话框中填入DataMap名称、描述、源对象数据格式以及目标对象格式。数据格式以json字符串定义,以源对象结构为例,下图中的格式表示源对象有一个字符串类型的属性“groupName",有一个数值类型的属性”firstNameLength",属性“persons”为数组,每一项是一个对象,项对象有“name"和"age"属性。目前支持”string"、"number"、"integer"、"array"、“object”这种数据类型,“array"只需要使用"[]"定义,"object"使用”{}“定义,其他数据类型在属性后面的字符串值中指定。
新建数据映射确定后跳转编辑映射关系页面,如下,窗体中使用树控件表示源对象和目标对象的数据格式,属性名前的”AB“表示这是一个“string"类型;”123“表示这是一个"integer"类型;”1.2“表示这是一个数值类型,可以带小数;”[ ]"表示是数组;“{ }”表示是“object”类型。”#item"是保留字,表示数组中的项。
页面左侧面板显示了所有可用的函数,可以将函数拖放到右侧。
二.属性映射
将鼠标移到源或目标数据三角形的“锚”上,按住左键拖放到要关联属性的锚上,下图表示将源数据的"groupName"属性复制到目标对象的”deptName"属性上。
三.数组映射
在数组之间拖放连线,可以建立数组之间的映射关系。数组映射用绿色线条表示。
如果象上图中只有数组映射并不会产生数组数据的转化,转换系统还缺少数组项的处理信息,下图则补充了项转化信息。也可以直接将源的”#item"和目标的“#item"连接,表示直接将项克隆到目标数组,不进行格式转换。
{
"groupName": "tools",
"firstNameLength": 1,
"persons": [{
"name": "刘大山",
"age": 20
},
{
"name": "王小壮",
"age": 27
}]
}
以上的数据经上图定义的DataMap转换后结果为:
{
"deptName": "tools",
"employees": [{
"first name": "刘大山",
"age": 20
},
{
"first name": "王小壮",
"age": 27
}]
}
四.表达式
表达式由连线、常量、函数等组合而成。从左侧拖放函数到右侧,添加连线构成表达式,表达式可以对数据进行更复杂的处理。
上图中的表达式表示使用“字符串处理.substr”函数对数组项name进行处理,对应的伪代码为“#item.name.substr(0, firstNameLength)”,紫色块表达一个值为“0"的常量。函数的具体用法请参考下面的函数说明。
{
"groupName": "tools",
"firstNameLength": 1,
"persons": [{
"name": "刘大山",
"age": 20
},
{
"name": "王小壮",
"age": 27
}]
}
以上的数据经上图定义的DataMap转换后结果为:
{
"deptName": "tools",
"employees": [{
"first name": "刘",
"age": 20
},
{
"first name": "王",
"age": 27
}]
}
五.数组过滤
数组过滤是一个特殊的数组映射,它对数组进行筛选,但同样不对数据进行转换,实际的转换依赖其下项上的映射定义。
上图的“数组映射.filter"通过”逻辑判断.greater"对数组进行过滤,只有符合条件的项才会转化到目标数组,上图直接将源项链接到目标项,项的数据直接克隆。
{
"flightNo": "zh998",
"passengers": [{
"name": "刘大山",
"age": 10
},
{
"name": "王小壮",
"age": 27
}]
}
以上的数据经上图定义的DataMap转换后结果为:
{
"passengers": [{
"name": "王小壮",
"age": 27
}]
}
除了使用”filter"对数组进行过滤外,也可以使用“数组处理.select"函数对数组进行过滤,但两者的用法不同。“filter"是数组映射,转换依赖于项上的映射,"select"是函数,直接输出转换的数组,和项上的其他映射没有关系。
“select”函数array指向要过滤的数组,condition为过滤表达式,value表示要放到数组中的数据,如果不对数组项进行改变,那么指同“#item”即可。
{
"flightNo": "zh998",
"passengers": [{
"name": "刘大山",
"age": 10
},
{
"name": "王小壮",
"age": 27
}]
}
因为项只取了passenger的name属性,因此经以上的DataMap转换后结果为:
{
"passengers": ["王小壮"]
}
六.取出数组中的某一项
“itemToObject”和“数组过滤”一样属于数组映射,但itemToObject链接到一个object对象,表示将数组中符合条件的项赋值给链接的对象,项到对象属性的转换取决于下面的映射定义。
getItem将数组映射到对象。
{
"name": "mk",
"users": [{
"name": "李明",
"age": 30,
"title": "hr"
},
{
"name": "孙立",
"age": 45,
"title": "manager"
}]
}
以上的数据经上图定义的DataMap转换后结果为:
{
"mk":{
"manager":"孙立"
}
}
如果需要按照索引取出项,使用getIndex函数,getIndex获取项在数组中的索引值,它的输入锚可以链接在“#item”上,也可以链接在项的任何属性上,比如下图,链接在“title”属性上,同样得到的是项在数组中的索引值。
single不是映射,是一个函数,和select类似,同样能对数组进行过滤,但只取符合条件的第一项。
single函数取出数组中“title"是”manager"的项的“name"属性,然后赋值给目标对象的”manager“属性。
{
"name": "mk",
"users": [{
"name": "李明",
"age": 30,
"title": "hr"
},
{
"name": "孙立",
"age": 45,
"title": "manager"
}]
}
以上的数据经上图定义的DataMap转换后结果为:
{
"name": "mk",
"manager":"孙立"
}
七.创建中间对象
中间对象是指在转换过程中要使用的临时对象,它的每个属性会有一个输入锚,输出为整个临时对象。也可以将中间对象看成一个特殊的函数,它的参数就是它的所有属性,但不同于一般的函数,它的参数没有预先确定,需要临时通过schema指定,函数的返回值就是对象本身。下图中,生成的对象有两个属性,分别为"key"和“value",”key"的值为链接属性的属性名,“value"的值为链接属性的值。最终这些对象通过”push"函数放入到一个数组中,数组再赋值给目标对象的“PropList"属性。
上面的操作最终定义的图形如下:
{
"ProcessDepartment": "1",
"Source": "7",
"FlightTicketType": "1"
}
以上的数据经上图定义的DataMap转换后结果为:
{
”PropList":[
{“key":"ProcessDepartment", "value":"1"},
{“key":"Source", "value":"7"},
{“key":"FlightTicketType", "value":"1"}
]
}
八.处理JSON格式字符属性
数据转换服务接收一个json格式的字符串,转换服务将json字符串转换为对象后使用,有时转换后的对象某个属性依然是一个json格式的字符串,如果希望在映射定义中能够将这个属性作为一个对象处理(而不是一个字符串),那么需要在新建DataMap时指定这个属性的位置。如下:
九.发布数据映射
DataMap定义如果没有发布还不能被调用。发布时需要提供至少一个拥有者(只有拥有者才能编辑DataMap)。
发布前至少需要提供一个测试数据,如果测试不通过不能发布。添加测试数据页面如下,如果源数据转换后和目标数据不一致,则测试不通过。
测试不通过时,状态显示红色,点击”查看转换结果“可以查找不通过的原因。
转换结果页面:
十.常量及函数
系统提供了简单地扩展函数的方法,以下是目前已提供的函数说明,随着需求的变化,系统中将会集成更多的函数。
1.常量
在发布DataMap时,系统将对DataMap进行编译,此时常量值将固化进编译后的DataMap。
1.1 字符串常量
可以用鼠标按住右下角三角形调整窗体大小
1.2 整型常量
只能输入整型
1.3 数值型常量(可以是小数)
可以是小数,也可以是整型
1.4 布尔型常量
用鼠标勾选设置值,选中时显示蓝色的叉,此时值为”true"
2.字符串处理函数
2.1 len 获取字符串长度
等价于以下javascript函数:
functionlen(string){
returnstring.length;
}
2.2 concat 连接字符串,默认连接两个字符串,想要连接更多,点击绿色加号添加要连接的字符串参数
等价于以下javascript函数:
function concat(){
let result="";
arguments.forEach(string=>{
result += string;
});
return result;
}
2.3 substr 获取字符串的了串
等价于以下javascript函数:
function substr(string, startIndex, length){
returnstring.substr(startIndex, length);
}
2.4 join 使用指定的分隔符将数组的项连接成一个字符串
等价于以下javascript函数:
function join(string, separator){
returnarray.join(string, separator);
}
2.5 split 使用分隔符分割字符串,返回一个字符串数组
等价于以下javascript函数:
function split(){
return string.split(separator);
}
4.数字处理函数
3.1 add 获取两个或多个数字的和
等价于以下javascript函数:
function (){
let result = 0;
arguments.forEach(number => {
result += number;
});
result;
}
3.2 subtract 获取两数的差
等价于以下javascript函数:
function subtract(a, b){
return a-b;
}
3.3 获取两个或多个数字的积
等价于以下javascript函数:
function multiply(){
letresult = 1;
arguments.forEach(number => {
result*=number;
});
returnresult;
}
3.4 devide 获取两数的商
等价于以下javascript函数:
function join(a, b){
returna/b;
}
3.数组处理函数
4.1 len 获取数组长度。
等价于以下javascript函数:
functionlen(){
returnarray.length;
}
4.2 select 从数组中过滤出符合条件的项,并从项中取出值放入目标数组中
等价于以下javascript函数:
function (array, conditionExpression, valueExpression){
let result = [];
array.forEach(item => {
let condition = conditionExpression.getValue(item);
if(conditiion){
result.push(valueExpression.getValue(item));
}
});
returnresult;
}
4.3 single 从数组中过滤出符合条件的项,并从项中取出值返回
等价于以下javascript函数:
function (array, conditionExpression, valueExpression){
let result = null;
for (let i = 0; i < array.length; i++) {
let item = array[i];
let condition = conditionExpression.getValue(item);
if(conditiion){
result = valueExpression.getValue(item);
break;
}
});
returnresult;
}
4.4 push向数组中添加项(至少添加一项,如果需要添加多项,点击绿色加号按钮添加)
如果array没有链接到数组,则新建数组。
等价于以下javascript函数:
function push(){
let result = arguments[0] || [];
for (let i = 1; i <arguments.length; i++) {
let condition = conditionExpression.getValue(item);
result.push(arguments[i]);
});
returnresult;
}
4.5 concat 连接多个数组后返回(至少两个,如果要连接多个,点击绿色按钮添加)
等价于以下javascript函数:
function concat(){
let result =arguments[0];
for (let i = 1; i <arguments.length; i++) {
let array=arguments[i];
array.forEach(item => {
result.push(item);
});
}
returnresult;
}
4.6 sum 求数组的汇总值
等价于以下javascript函数:
function sum(array, fieldExpression){
let result = 0;
array.forEach(item => {
letitemValue = fieldExpression.getValue(item);
result += itemValue;
});
returnresult;
}
4.7 avg 求数组中值的平均值
等价于以下javascript函数:
function avg(array, field){
let result = 0;
array.forEach(item => {
letitemValue = fieldExpression.getValue(item);
result += itemValue;
});
returnresult / array.length;
}
4.8 min 取出数组中最小的值
等价于以下javascript函数:
function min(array, fieldExpression){
let minValue = fieldExpression.getValue(array[0]);
for (let i = 1; i <array.length; i++) {
let value = fieldExpression.getValue(array[i]);
if (minValue > value)
minValue = value;
}
return minValue;
}
4.9 max 取出数组中最大的值
等价于以下javascript函数:
function max(array, fieldExpression){
let maxValue = fieldExpression.getValue(array[0]);
for (let i = 1; i <array.length; i++) {
let value = fieldExpression.getValue(array[i]);
if (maxValue < value)
maxValue = value;
}
return maxValue;
}
4.9 getIndex 获取项在数组中的索引值
获取项在数组上的索引,该函数的输入线必须连接在数组的项上,但可以连接在“#item"上或项对象的属性上,返回的值相同,以下三种连接方式都是合法的。
等价于以下javascript函数:
function getIndex(array, item){
for (let i = 1; i <array.length; i++) {
if( array[i] === item){
returni;
}
}
return -1;
}
5.逻辑运算函数
5.1 and 多个布尔变量的与操作
等价于以下javascript函数:
functionand(){
for (let i = 0; i <arguments.length; i++) {
if (!arguments[i].getValue(dataContext)) {
return false;
}
}
return true;
}
5.2 or 多个布尔变量的或操作
等价于以下javascript函数:
functionor(){
for (let i = 0; i <arguments.length; i++) {
if (arguments[i].getValue(dataContext)) {
return true;
}
}
return false;
}
6. 逻辑判断函数
5.1 if else判断
等价于以下javascript函数:
functionifelse(){
let groupCount =(arguments.length - 1) / 2;
for (let i = 0; i < groupCount; i++) {
let index = i * 2;
if (arguments[index]) {
returnarguments[index + 1];
}
}
returnarguments[arguments.length - 1];
}
5.2 switch判断
等价于以下javascript函数:
functionswitch(){
let comparedValue =arguments[0];
let groupCount =(arguments.length - 2) / 2;
for (let i = 0; i < groupCount; i++) {
let index = i * 2 + 1;
let caseValue =arguments[index]
if(caseValue===comparedValue) {
returnarguments[index + 1];
}
}
returnarguments[arguments.length - 1];
}
5.3 equal判断
等价于以下javascript函数:
functionequal(a, b){
return a === b;
}
5.4 notequal判断
等价于以下javascript函数:
functionnotequal(a, b){
return a != b;
}
5.5 greater判断
等价于以下javascript函数:
functiongreater(a, b){
return a > b;
}
5.6 greaterequal判断
等价于以下javascript函数:
functiongreaterequal(a, b){
return a >= b;
}
5.7 less判断
等价于以下javascript函数:
functionless(a, b){
return a < b;
}
5.8 lessequal判断
等价于以下javascript函数:
functionlessequal(a, b){
return a <= b;
}
6. 对象操作函数
6.1 parseJson字符串转对象
将字符串转换为Object对象,这个函数特殊性在于它产生的对象将成为源对象的一部份,这部份也能够参与数据映射。非必要情况下,不要使用这个函数,在易用性和性能上它不如第八节”处理JSON格式字符串属性“中的方法,但它提供的更好的灵活性。
将parseJson拖放到设计面板后将弹出如下对话框:
该对话框要求输入对象的结构,确定后如下,它接收一个字符串,输出一个每个属性都带“锚”的对象。
等价于以下javascript函数:
functionstringToObject(string){
return JSON.parse(string);
}
6.2 createObject创建临时对象,它的意义请参考第七节“创建中间对象”
将createObject拖放到设计面板后将弹出如下对话框,它要求输入临时对象的结构。
确定后如下:
等价于以下javascript函数:
functioncreateObject(keyPropertyValue, valuePropertyValue, propTypePropertyValue){
return {"Key":keyPropertyValue,"Value":valuePropertyValue,"PropType":propTypePropertyValue,};
}
5.3 stringify 对象转字符串
等价于以下javascript函数:
functionstringify(object){
return JSON.parsestringify(object);
}
5.4 getPropertyValue 获取属性值
等价于以下javascript函数:
functiongetPropertyValue(object,propetyName){
return object[propetyName];
}
5.5 getPropertyName 获取属性名
获取指向对象的属性名。
十一.调用数据映射
com.ctrip.soa.flight.crawler.crawlertoolsworkflow.v1
crawlertoolsworkflow
1.0.11
调用convertData方法。
参数:
DataMapId:要调用的映射id
AccessKey:访问Key,本参数是为了校验传入的DataMapId值是否正确,防止误传,如果是DataMap拥有者,可以在DataMap列表页查看该值,否则需要向拥有者询问该值。
Source:源对象(需要进行转换的对象)JSON字符串。
返回值:
转换后的目标对象。
网友评论