API数据格式转换方法学习
将数据转为行列模式,方便使用统一数据格式来循环遍历来输出所有属性,并且能根据需要转换不同的值.
例子实现是用vue来演示的
一般的实现方式
原始数据是外面是items包了一层,是数组格式,然后里面每一个数组元素都是一个对象,代表每一个item,每个item里面分别是属性和值
原始数据:
"items": [ { "goods_name": "哈哈哈", "goods_spec_name": "11111", "goods_price": 100, "goods_num": 1, "status": 2, }, { "goods_name": "哈哈哈11111", "goods_spec_name": "11111", "goods_price": 100, "goods_num": 1, "status": 2, } ]
一般的写法会根据各个值进行遍历,这样的话,
代码会很长,也不整洁
不灵活,如果要处理一些值的格式化变化,就需要修改循环里面的代码,或者数据格式万一改变了,那么也要修改循环里面的代码,很容易出错
商品名: @{ {item.goods_name}}规格: @{ {item.goods_spec_name}}单价: @{ {(item.goods_price/100).toFixed(2)}}数量: @{ {item.goods_num}}订单状态: 待支付 待发货 待发货 交易完成
更好的实现方式
用更好的方式实现去解决以上的问题
将原先的数据输出改成行列模式,每一行包含多个列,每一行代表一个原始数据对象,每一列代表一个原始数据对象的一个属性,节省了输出代码,也整洁了逻辑,每一行都代表一种类型的属性,例如第一行都是商品名称相关的,第二行都是商品状态相关的
转换是需要一个转换函数进行的,将原始数据和输出数据之间搭建一个桥梁,这样有什么修改都可以修改桥梁,避免去处理输出数据,也不用去改变原始数据(很多时候上层api数据格式是不能改变的)
转换过程可以对值进行一些单独的转换处理,很灵活
@{ { col[0] }} @{ { col[1] }}
这是转换函数,转换过后的值才能被行列写法的循环遍历使用
function change_list_data(all) { var ret = []; var data, x, y, z, row, col, def; var key, val, opt; var fmt = [ //建立一个过渡格式 [ // 行 // 格式说明;[key, 标题名字, 值转换函数, 选项转换函数] ['goods_name', '商品名', null, null], // 列 ['goods_spec_name', '规格', null, null], ['goods_price', '单价', fee2yuan, null], //这里有一个价格的转换函数,将分转为元的单位 ['goods_num', '数量', null, null] ], [ ['status', '状态', null, null] ] ]; for (x = 0; x < all.length; ++x) { //遍历原始数据,并且每次循环的时候创建一个data变量,保存的是原始数据的当前循环的值,即保存了一个商品对象的信息,用来获取原始数据的数据的 data = all[x]; row = []; // 创建一个行变量 for (y = 0; y < fmt.length; ++y) { //遍历过渡格式的行 col = []; //创建一个列变量 for (z = 0; z < fmt[y].length; ++z) { //遍历过渡格式的列 def = fmt[y][z]; //获得过渡格式的列的值,如fmt[0][0]就是['goods_name', '商品名', null, null] key = def[0]; // 先保存key if (typeof def[2] == 'function') { // 看看值是否需要做转换处理 val = def[2](data[key]); //执行特殊转换函数,并且传入原始数据的这个key的值然后,例如转换价格 } else { val = data[key]; } if (typeof def[3] == 'function') { // 看看选项是否需要做转换处理 opt = def[3](val, data[key]);//类似做法 } else if (def[3] === null) { opt = {}; //因为选项不能null } else { opt = def[3]; } //将修改后的数据push到列里 col.push([def[1], val, opt]); } //将修改后的列数据push到行里 row.push(col); } //将修改后的行数据push到行里 ret.push(row); } return ret;}
总的来说:
关键的关键是通过一个key来实现数据沟通,
['goods_name', '商品名', null, null]
,这里的goods_name就是一个key,因为对应到原始数据的goods_name,这样转换前后的数据之间就能够互相处理
这是转换后的数据是:
[ [ //这里是一个商品对象 [ //这里是一个商品的一行属性,每行能够显示一种模式的列属性, [ //这里是一个商品的列属性,每一行有多列,这样可以很方便的使用0,1这样来调用数组的数据,简化了操作 0=>'商品名', 1=>'哈哈哈' ], [ 0=>'规格', 1=>'1' ] ], [ //这里是一个商品的一行属性 [ 0=>'状态', 1=>'1' ], ] ], [ //这里是第二个商品对象 [ [ 0=>'商品名', 1=>'哈哈哈111' ], [ 0=>'规格', 1=>'1111' ] ], [ [ 0=>'状态', 1=>'2' ], ] ] ]
关于灵活地对值进行处理
在过渡格式里面,每一列都有4个参数
// 格式说明;[key, 标题名字, 值转换函数, 选项转换函数] ['goods_name', '商品名', null, null], // 列
在循环的时候通过判断是否是转换函数来进行转换
if (typeof def[2] == 'function') { val = def[2](data[key]); //这里拆开来看就是一个函数传入参数的处理,因为def[2]是一个含糊是,然后()进行传参 } else { val = data[key]; }
例如状态值,在api数据里面是数字,但是在输出显示的时候就要用文字
所以传入一个状态转换的函数,然后方便转换数字为文字['status', '状态', statusT, null]//那么就使用这个转换函数//val = def[2](data[key]);val = statusT(data[key]); //实际上会变成这样//例如statusT是这样的,传入数字,返回文字function statusT(code) { var str; switch (code) { case 0: str = '未支付'; break; case 1: str = '待发货'; break; case 2: str = '已发货'; break; } return str;}