接口返回动态列名及动态列数据结构代码方案
在开发过程中,有时我们需要处理动态表头和动态列数据的问题。特别是在一些数据统计或报表类需求中,列名和数据都可能随着时间或条件发生变化。本文将结合实际代码和表格展示,详细说明如何在接口中实现返回动态列名和动态列数据。
一、问题描述
假设我们在处理房屋供应数据时,不仅需要返回基础的列信息(如房型、面积、均价等),还需要动态地返回不同日期下的供应套数,如下图所示:
从图中可以看出,日期列是动态生成的,且供应套数也是根据不同日期进行展示。为了实现这种需求,我们需要设计一种灵活的接口响应结构。
二、设计思路
-
定义实体类:我们需要一个实体类来承载返回的数据结构,包括房屋类型、房型、面积、均价、供应总套数等基本字段,同时还要处理动态列数据。
-
动态列解析:通过将数据库中的某个字段(如
val
字段)存储的聚合值解析成多个动态列,这些列代表不同的日期,并且日期下的值表示供应套数。 -
动态列名存储:使用
LinkedHashSet
来保证列名的唯一性和有序性,同时确保列名是动态生成的,且按照日期排序。
三、代码实现
1. 实体类设计
首先,定义一个实体类 SupplyFeaturesVo
来承载数据。为了简化 val
字段的处理,我们在实体类中对其做了序列化忽略的标注。
@Data
public class SupplyFeaturesVo implements Serializable {
/**
* 房屋类型
*/
private String houseType;
/**
* 房型
*/
private String roomType;
/**
* 面积
*/
private String acg;
/**
* 均价
*/
private String avg;
/**
* 供应(成交)总套数
*/
private String num;
/**
* 聚合值 2022-03-27@10,2022-03-26@4
*/
@JSONField(serialize = false)
private String val;
}
2. 处理逻辑
接下来,通过后端代码处理数据库返回的数据。我们要解析 val 字段,将其转化为动态列,并计算总供应套数。
public ItemResp<SupplyFeaturesResp> supplyFeaturesAll(SupplyFeaturesReq req) {
//房屋类型条件处理
req.setHouseType(SqlUtil.newHouseTypeConditionToSql(req.getHouseType(), "a.housetype"));
// 获取数据
List<SupplyFeaturesVo> resultList = newHouseMarkerMapper.supplyFeaturesAll(req);
if (CollUtil.isEmpty(resultList)) {
return new ItemResp<>(ApiSaasCodeEnums.NoData);
}
// 保存动态数据
List<Map<String, Object>> list = new ArrayList<>();
LinkedHashSet<String> dynamicDisplayFields = new LinkedHashSet<>();
resultList.forEach(t -> {
Map<String, Object> listBean = MapUtils.entityToMap(t);
String val = t.getVal();
Integer supplyNum = 0;
if (StrUtil.isNotBlank(val)) {
//val : 2022-03-27@10,2022-03-26@4
String[] valArrays = val.split(",");
for (String bean : valArrays) {
String[] data = bean.split("@");
String dateTime = data[0];
String num = data[1];
// 动态添加列名
dynamicDisplayFields.add(dateTime);
// 动态添加列值
listBean.put(dateTime, data[1]);
// 计算供应总数
supplyNum = supplyNum + Convert.toInt(num, 0);
}
}
// 设置供应总套数
listBean.put("num", supplyNum);
list.add(listBean);
});
// 对动态列名进行排序
List<String> dynamicDisplayFieldList = dynamicDisplayFields.stream().sorted(Comparator.comparing(String::valueOf)).collect(Collectors.toList());
// 返回结果
SupplyFeaturesResp result = new SupplyFeaturesResp();
result.setSets(new SupplyFeaturesResp.SupplyFeaturesData(list.size(), list));
result.setDynamicDisplayFields(dynamicDisplayFieldList);
return new ItemResp<>(result);
}
3. 核心解析逻辑
在代码中,val 字段存储的是聚合值(如 2022-03-27@10,2022-03-26@4),我们通过 split 方法将其解析为动态的列名(日期)和列值(供应数量)。随后,将这些动态列存储到 listBean 对象中,并动态生成列名列表用于前端展示。
4. 动态列名和数据结构
返回的响应数据结构将包含两个部分:
- 动态列名:由不同日期组成的列名集合,用于动态展示。
- 数据集合:每一行包含房型、面积、均价、供应总套数,以及多个动态列(供应日期和对应的供应数量)。
四、总结
本文通过具体的代码示例展示了如何在接口中返回动态列名及动态列数据结构。在处理诸如报表、统计类数据时,动态列的生成和处理是一项常见需求,掌握这种处理方式能够让我们的代码更加灵活,满足不断变化的业务需求。
希望这篇文章对你在处理动态列数据时有所帮助。