1

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,
    }    
]

一般的写法会根据各个值进行遍历,这样的话,

  1. 代码会很长,也不整洁

  2. 不灵活,如果要处理一些值的格式化变化,就需要修改循环里面的代码,或者数据格式万一改变了,那么也要修改循环里面的代码,很容易出错

<template v-for="item in listItems">
                    <li class="order-border">
                        <div class="list-item">
                            <div class="li-inline li-40">
                                <span>商品名:</span><span>@{{item.goods_name}}</span>
                            </div>
                            <div class="li-inline li-33">
                                <span>规格:</span><span>@{{item.goods_spec_name}}</span>
                            </div>
                            <div class="li-inline li-15">
                                <span>单价:</span><span>@{{(item.goods_price/100).toFixed(2)}}</span>
                            </div>
                            <div class="li-inline li-10">
                                <span>数量:</span><span>@{{item.goods_num}}</span>
                            </div>
                        </div>
                            <div class="li-inline li-15">
                                <span>订单状态:</span>
                                <span v-if="item.status == 0">
                                    待支付
                                </span>
                                <span v-else-if="item.status == 1">
                                    待发货
                                </span>
                                <span v-else-if="item.status == 2">
                                    待发货
                                </span>
                                <span v-else-if="item.status == 3">
                                    交易完成
                                </span>
                            </div>
                        </div>
                    </li>
</template>

更好的实现方式

用更好的方式实现去解决以上的问题

  1. 将原先的数据输出改成行列模式,每一行包含多个列,每一行代表一个原始数据对象,每一列代表一个原始数据对象的一个属性,节省了输出代码,也整洁了逻辑,每一行都代表一种类型的属性,例如第一行都是商品名称相关的,第二行都是商品状态相关的

  2. 转换是需要一个转换函数进行的,将原始数据和输出数据之间搭建一个桥梁,这样有什么修改都可以修改桥梁,避免去处理输出数据,也不用去改变原始数据(很多时候上层api数据格式是不能改变的)

  3. 转换过程可以对值进行一些单独的转换处理,很灵活

<!--html的循环遍历减少了一半的代码,而且很简单,遍历listitems获得每一个item,然后遍历item获得每一个属性和对应的值-->
                <template v-for="item in listItems">
                    <li>
                        <div  v-for="row in item">
                            <div v-for="col in row">
                                <span class="label">@{{ col[0] }}</span>
                                <span class="label-value">@{{ col[1] }}</span>
                            </div>
                        </div>
                    </li>
                </template>

这是转换函数,转换过后的值才能被行列写法的循环遍历使用

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;
}

总的来说:

  1. 关键的关键是通过一个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;
}

线上猛如虎
2.2k 声望178 粉丝

你们都有梦想的,是吧.怀抱着梦想并且正朝着梦想努力的人,寻找着梦想的人,我想为这些人加油呐喊!