前言
昨天组员在业务开发中遇到了一个菜品领取登记表修改菜品后,如何将修改后的数据以json的形式发给后端的问题,我在解决这个问题时,发现这个问题蛮有意思,于是就将这个问题发到了沸点和群里,看了大家的解决思路后,学到了不少知识。
接下来就以这个问题为背景,讲解这个功能如何实现,欢迎各位感兴趣的开发者阅读本文。
问题背景
如上图所示,在菜品领取登记表里,用户可以里输入各个菜品的数量,输入完成后点保存生成json数据,调接口将供应日期放进生成的json数据一并发给后端,后端拿到json数据后修改数据库中的数据。
解决思路
观察菜品领取登记表后,我们发现表中姓名为固定数据,其他字段都是后端返的动态数据,表格的内容也是动态的,每行数据描述了其姓名所对应的菜品以及菜品数量,我们根据这些已知条件整理下思路,将这些数据用js从dom中提取出来。
- 获取供应日期,存进一个变量中。
- 获取表头数据,存进一个数组中。
- 获取表格内容,存进一个数组中。
- 遍历表格内容,将表格中的数据与表头一一对应,存进一个JSON数组中。
- 将供应日期和表格内容的json数组放进一个对象中,调接口将数据发送给后端。
解决方案
对页面进行分析后,我们得到了解决思路,接下来我们将上述思路转换为代码:
- 菜品领取登记表的DOM结构如下:
<!--查询列表--> <table class="search"> <tbody><tr> <td> 姓名: <input type="text" name="xm"> 供应日期: <input type="text" id="gyrq" name="gyrq" onclick="wd.edit.datePicker({dateFmt:'yyyy-MM-dd'})" value="2020-04-30" id="gyrq"> <button type="button" class="btn" onclick="document.getElementById('form').submit();">查询</button> </td> <td style="text-align: right;"> <button type="button" class="btn" id="dc">导出</button> <button type="button" class="btn" id="dy">打印</button> </td> </tr> </tbody> </table> <div class="list-div" id="tb1"> <table class="list"> <thead> <tr> <th style="text-align: center;">姓名</th> <th style="text-align: center;"> 牛肉03 </th> <th style="text-align: center;"> 鸡肉002 </th> </tr> </thead> <tbody wdoddclass="list-odd" wdevenclass="list-even" wdmouseoverclass="list-mouseover" id="wdTbody0"> <tr class=" list-odd"> <td style="text-align: center;"> 青秀山 </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="0"> </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="15"> </td> </tr> <tr class=" list-even"> <td style="text-align: center;"> a </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="0"> </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="0"> </td> </tr> </tbody> </table> </div>
- 根据dom结构编写js代码获取我们需要的数据
<tbody><tr> <td> 姓名: <input type="text" name="xm"> 供应日期: <input type="text" id="gyrq" name="gyrq" onclick="wd.edit.datePicker({dateFmt:'yyyy-MM-dd'})" value="2020-04-30" id="gyrq"> <button type="button" class="btn" onclick="document.getElementById('form').submit();">查询</button> </td> <td style="text-align: right;"> <button type="button" class="btn" id="dc">导出</button> <button type="button" class="btn" id="dy">打印</button> </td> </tr> </tbody> </table> <div class="list-div" id="tb1"> <table class="list"> <thead> <tr> <th style="text-align: center;">姓名</th> <th style="text-align: center;"> 牛肉03 </th> <th style="text-align: center;"> 鸡肉002 </th> </tr> </thead> <tbody wdoddclass="list-odd" wdevenclass="list-even" wdmouseoverclass="list-mouseover" id="wdTbody0"> <tr class=" list-odd"> <td style="text-align: center;"> 青秀山 </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="0"> </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="15"> </td> </tr> <tr class=" list-even"> <td style="text-align: center;"> a </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="0"> </td> <td style="text-align: center;"> <input type="text" style="width: 100px;" name="mc" value="0"> </td> </tr> </tbody> </table> </div>
- 根据dom结构编写js代码获取我们需要的数据
// 表格对象 let tableObj = {}; // 供应日期 tableObj.gyrq = $("#gyrq").val(); // 获取所有的标题 const titleArr = $("#tb1 table thead tr"); // 获取所有的内容 const contentArr = $("#tb1 table tbody"); // 列表数据 let data = []; // 遍历所有的内容 for(let i = 0; i < contentArr.children().length; i++){ // 每一个内容对象 let obj = {}; // 遍历所有的标题 for(let j = 0; j < titleArr.children().length; j++){ // 获取每个标题 let key = (titleArr.children().eq(j).html()).replace(/\s/g, ""); if(j ===0){ // 姓名的dom结构是html obj[`${key}`] = (contentArr.children().eq(i).children().eq(j).html()).replace(/\s/g, ""); }else{ // 其他字段的dom结构是input obj[`${key}`] = (contentArr.children().eq(i).children().eq(j).children().val()).replace(/\s/g, ""); } } // 将每个对象放进数组里 data.push(obj); } tableObj.data = data;
- 调用接口将获取到的json数据发给后台
$.ajax({ url:"", data:tableObj, type:"POST", success:(res)=>{ } })
JSON二次处理
上述代码将dom中的数据转成json后,后端说这不是他要的格式,这种数据他无法解析,然后发了json格式给我,让我按照他的格式转一下。
我跟后端说:你直接在你那边转成你要的格式就好了。后端:你直接在页面转,我后端转的话会造成没必要的资源浪费。我:行吧,那我转吧。
- 后端给我的json格式:
{ time:"xxxx-xx-xx", data:[ { name:"xx", title:"", num:"" } ] }
- 我解析的json格式
{ "time":"2020-04-30", "data":[ {"姓名": "青秀山", "牛肉03": "0", "鸡肉002": "15"}, {"姓名": "a", "牛肉03": "0", "鸡肉002": "0"} ] }
难点分析
后端需要的数据为把每个人的数据拆分出来。
例如,名字为青秀山客户,他点了牛肉03,数量为0,鸡肉002数量为15。
名字为a的客户,他点了牛肉03数量为0,鸡肉002数量为0。
转换成json后的代码为:
{ "time": "2020-04-30", "data": [ { "name": "青秀山", "title": "牛肉03", "num": "0" }, { "name": "青秀山", "title": "鸡肉002", "num": "15" }, { "name": "a", "title": "牛肉03", "num": "0" }, { "name": "a", "title": "鸡肉002", "num": "0" } ] }
观察我们生成的json数据和后端需要的json数据后,发现了如下规律:
- 我们生成的json数据中,姓名是已知字段,其他字段是动态未知的。
- 后端需要的json数据中,data中json对象的个数,是根据我们生成的json数据中的动态字段数量决定的。
代码实现
知道规律后,我们就可以用js实现这个解析器了。
/** * json解析器 * @param jsonObj * @returns {{}} * @constructor */ const JsonParse = function (jsonObj= {}) { let resultObj = {}; // time是固定值,所以可直接取出来 resultObj.time = jsonObj.time; resultObj.data = []; for (let i = 0; i < jsonObj.data.length; i++){ // 获取数组里的每一项对象 const dataObj = jsonObj.data[i]; // 转换后的每一项json对象 let resultDataObj = {}; // 转换后的对象姓名,因为姓名为固定值,遍历对象时需要加上。 let resultDataObjName = ""; // 遍历数组里的每一项对象 for (let key in dataObj){ // 如果dataObj对象里的key不存在则终止本次循环 if(!dataObj.hasOwnProperty(key)) continue; // 姓名为固定条件 if(key === "姓名"){ // 记录名字 resultDataObjName = dataObj["姓名"]; }else{ // 动态条件,此时key为除姓名以外的值,获取当前key的名字和数量 resultDataObj.name = resultDataObjName; resultDataObj.title = key; resultDataObj.num = dataObj[key]; // name、title、num为已知值,将当前对象放进结果对象的data里 resultObj.data.push(resultDataObj); // 清空当前对象,继续下一个key的遍历 resultDataObj = {}; } } } return resultObj; }
对上述代码进行运行测试
// 测试数据 const dataObj ={ "time":"2020-04-30", "data":[ {"姓名": "青秀山", "牛肉": "0", "鸡肉": "15"}, {"姓名": "a", "牛肉": "0", "鸡肉": "0","鸡蛋":"12"}, {"姓名": "test", "猪肉": "0", "鸭肉": "0"} ] } console.log(JsonParse(dataObj));
网友的实现思路
将我们生成的json转为后端所需要的格式,这是一个有意思的问题。于是我将这个问题发到了群里和掘金沸点,看看大家的解题思路,接下来我就把大家的实现代码贴出来。
- 沸点评论区网友:@boboka123的解决方案
- 校友@_Dreams的解决方案
- 群友@Cavey的解决方案
- 群友@ssh的解决方案
- 群友@聆听心底的浪潮、的解决方案
写在最后
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
- 本文首发于掘金,未经许可禁止转载💌