JSONObject序列化时间异常
- 场景:Redis数据缓存
- 数据格式:Map集合
{
"min": {
"windPowerSupply": 381.2,
"storagePowerSupply": 20,
"wge2": 385.8,
"opticalPowerSupply": 0,
"peakShavingCapacity": 2104.1,
"thermalPowerSupply": 2564.1,
"powerSupplyCapacity": 3778.1,
"loadForecast": 3182.2,
"powerSupplyMargin": 595.9,
"allocationReserve": 148,
"hydraulicPowerSupply": 575,
"forecastDate": "2023-02-09 10:10:10",
"peakRegulationMargin": 1078.1
},
"max": {
...
},
"details": [
...
]
}
- 问题:JSONObject转换后(时间字段变成了毫秒数)
{
"min": {
"windPowerSupply": 381.2,
"storagePowerSupply": 20,
"wge2": 385.8,
"opticalPowerSupply": 0,
"peakShavingCapacity": 2104.1,
"thermalPowerSupply": 2564.1,
"powerSupplyCapacity": 3778.1,
"loadForecast": 3182.2,
"powerSupplyMargin": 595.9,
"allocationReserve": 148,
"hydraulicPowerSupply": 575,
"forecastDate": 1675850400000,
"peakRegulationMargin": 1078.1
},
"max": {
...
},
"details": [
...
]
}
-
问题分析
-
Redis格式化的原因(确实存在,但这里不是Redis的问题)
Redis会格式化会将时间字段转换成毫秒数进行存储,转出时,接收对象可被序列化成功,不会影响数据结构
-
序列化导致的,时间字段存放在Map集合中,JSONObject直接将时间字段转换成了毫秒数(主要)
-
转入时,Date类型数据会被转换成毫秒数
-
转出时,元数据不会被转换成Date类型数据
-
-
-
解决方案
- 用单独的类对时间字段进行封装,并将类进行序列化,json转换前后不会受到影响
序列化类:BalanceForecastDataVo.class
@Data
public class BalanceForecastDataVo implements Serializable {
private List<PmBalancedForecastDetailVo> chart;
private List<PmBalancedForecastDetailVo> details;
private PmBalancedForecastDetailVo max;
private PmBalancedForecastDetailVo min;
}
定时任务:TimingTask.class
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TimingTask {
private final IPmBalancedForecastService iPmBalancedForecastService;
private final StringRedisTemplate stringRedisTemplate;
private void makeCachePhyc() {
BalanceForecastDataVo totalNew = iPmBalancedForecastService.getTotalNew();
stringRedisTemplate.opsForValue()
.set(PowerGenerationGroup.PHYC_ZL, JSONObject.toJSONString(totalNew), 60, TimeUnit.SECONDS);
}
}
目标方法:getTotalNew
public BalanceForecastDataVo getTotalNew() {
BalanceForecastDataVo balanceForecastDataVo = new BalanceForecastDataVo();
String redisData = stringRedisTemplate.opsForValue().get(PowerGenerationGroup.PHYC_ZL);
if(NullCheckUtils.isNotNull(redisData)) {
balanceForecastDataVo = JSONArray.parseObject(redisData, BalanceForecastDataVo.class);
return balanceForecastDataVo;
}
}
- 其他序列化方式,尝试过,但是未找到靠谱方案