在指定特定时间段时,我们准备一个Web API,该API返回该时间段内每个日期的数据。
具体来说,POST
{"targetFrom": "2016-04-01", "targetTo": "2016-04-03"}}
返回以下JSON数据。
{
"meta": {
"StartTime": "2017-06-01T06:50:28.001344102Z",
"execute_time": 7532.0517,
"host": "49a6ced149d2",
"rid": ""
},
"result": {
"2016-04-01": {
"0:num": 121,
"0:price": 5244614,
"1:num": 124,
"1:price": 6324547,
"2:num": 115,
"2:price": 5604491
},
"2016-04-02": {
"0:num": 125,
"0:price": 6321222,
"1:num": 117,
"1:price": 5835030,
"2:num": 118,
"2:price": 5771826
},
"2016-04-03": {
"0:num": 118,
"0:price": 5486071,
"1:num": 131,
"1:price": 6563447,
"2:num": 111,
"2:price": 5740078
},
"subTotal": {
"total_2016-04-01_num": 360,
"total_2016-04-01_price": 17173652,
"total_2016-04-02_num": 360,
"total_2016-04-02_price": 17928078,
"total_2016-04-03_num": 360,
"total_2016-04-03_price": 17789596
},
"total": {
"num": 1080,
"price": 52891326
}
}
}
问题是日期字段的一部分,如“2016-04-01”。 我想在SpringBoot的应用程序端接受这个,考虑处理修改,并希望定义一个合适的模型。 但是,我找不到一个好的方法。
首先,我认为以下是愚蠢的行为。
@JsonProperty("2016-04-01")
private ResAnalyzeResultDayDto result_20160401;
这是愚蠢的,因为它无法对应于在查询时依赖于参数targetFrom或targetTo的返回数据。
那么,我们如何定义一个模型来处理具有根据请求动态变化的Field的响应数据? 如果你有个好主意,请告诉我。
附加说明: 我编写以下代码时,我的相处并不好。
@JsonProperty("[0-9]{4}-[0-9]{2}-[0-9]{2}")
private Map<String,ResAnalyzeResultSubTotalDayDto> maps;
首先,“@ JsonProperty”似乎无法使用正则表达式,我认为它不会自动设置地图的键。
请求部分的代码使用“RestTemplate”。
ReqTotalSalesStatusDto reqGoMonth = new ReqTotalSalesStatusDto();
reqGoMonth.setStrTo("2016-04-03");
reqGoMonth.setStrFrom("2016-04-01");
// Jackson2HttpMessage
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<ResAnalyzeDto> resultGoMonth = restTemplate.exchange(
"http://localhost:18000/analyze"
, HttpMethod.POST
, new HttpEntity<>(reqGoMonth)
, ResAnalyzeDto.class);
答案 0 :(得分:1)
您可以将所有结果字段添加到地图对象中:
private Map<String,Object> result;
result.forEach((k,v)->{
System.out.println("key: " + k + " value: " + v);
if("total".equals(k)){
Total total = (Total) v;
} else if("subTotal".equals(k)) {
SubTotal subTotal = (SubTotal) v;
} else {
ResAnalyzeResultDayDto resAnalyzeResultDayDto = (ResAnalyzeResultDayDto) v;
}
});
之后你可以检查钥匙。至于你的例子,map值可以是3个不同的对象。 Total,SubTotal或DayInfo(ResAnalyzeResultDayDto)。您可以轻松了解总计和小计,并可以将它们转换为相应的对象类型。对于地图的其余值,他们将被投射到ResAnalyzeResultDayDto。
答案 1 :(得分:0)
谢谢你,barbakini
我按照我教的方式尝试过,但我不能在演员阵容中表现出色,现在迈出了一步。
日志如下
key: 2016-04-01 value: {0:num=121, 0:price=5244614, 1:num=124, 1:price=6324547, 2:num=115, 2:price=5604491}
v.toString(): {0:num=121, 0:price=5244614, 1:num=124, 1:price=6324547, 2:num=115, 2:price=5604491}
2017-06-02 17:12:49.962 [maekawa-PC-http-nio-9999-exec-3] ACS XXX:[id: tenant_id:] url:/api/v1/totalsalesstatus/common3 status:200 elapsedNanoTime:8455258
2017-06-02 17:12:49.963 [maekawa-PC-http-nio-9999-exec-3] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to jp.co.temp.sample.management.report.api.dto.ResAnalyzeResultDayDto] with root cause
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to jp.co.temp.sample.management.report.api.dto.ResAnalyzeResultDayDto
at jp.co.temp.sample.management.report.api.TotalSalesStatusCommandService.lambda$createFinalResultObj3$3(TotalSalesStatusCommandService.java:609)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at jp.co.temp.sample.management.report.api.TotalSalesStatusCommandService.createFinalResultObj3(TotalSalesStatusCommandService.java:600)
答案 2 :(得分:0)
模型
@Data
public class ResAnalyzeResultDayDto {
@JsonProperty("0:num")
private int num0;
@JsonProperty("0:price")
private int price0;
@JsonProperty("1:num")
private int num1;
@JsonProperty("1:price")
private int price1;
@JsonProperty("2:num")
private int num2;
@JsonProperty("2:price")
private int price2;
}
码
private ResponseEntity<TotalSalesStatus> createFinalResultObj3(TotalSalesStatus resultObj,
List<ResponseEntity<ResAnalyzeDto3>> goResponseEntityList ,String disposalDate) {
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
this.logger.info("■■UT:[{}] ", methodName);
int sumTotalNum = 0;
int sumTotalPrice = 0;
TotalSalesStatusGrandson totalSalesStatusDay = new TotalSalesStatusGrandson();
resultObj.setTotalSalesStatusDay(totalSalesStatusDay);
TotalSalesStatusGrandson totalSalesStatusMonth = new TotalSalesStatusGrandson();
resultObj.setTotalSalesStatusMonth(totalSalesStatusMonth);
boolean targetMonthFlag = false;
for(ResponseEntity<ResAnalyzeDto3> e : goResponseEntityList){
ResAnalyzeDto3 dto = e.getBody();
ResAnalyzeMetaDto meta = dto.getMeta();
Map<String,Map<String,?>> resu = dto.getResult();
this.logger.info("■■UT:[{}] ResAnalyzeMetaDto :{}", methodName,meta.toString());
this.logger.info("■■UT:[{}] ResAnalyzeResultDto:{}", methodName,resu.toString());
resu.forEach((k,v)->{
System.out.println("key: " + k + " value: " + v);
System.out.println("v.toString(): " + v.toString());
String val = v.toString();
ObjectMapper mapper = new ObjectMapper();
if("total".equals(k)){
// ResAnalyzeResultTotalDto total = (ResAnalyzeResultTotalDto) v;
try {
ResAnalyzeResultTotalDto total = mapper.readValue(val,ResAnalyzeResultTotalDto.class);
} catch (Exception e1) {
e1.printStackTrace();
}
} else if("subTotal".equals(k)) {
// ResAnalyzeResultSubTotalDto subTotal = (ResAnalyzeResultSubTotalDto) v;
try {
ResAnalyzeResultSubTotalDto subTotal = mapper.readValue(val,ResAnalyzeResultSubTotalDto.class);
} catch (Exception e1) {
e1.printStackTrace();
}
} else {
// ResAnalyzeResultDayDto resAnalyzeResultDayDto = (ResAnalyzeResultDayDto) v;
try {
ResAnalyzeResultDayDto resAnalyzeResultDayDto = mapper.readValue(val,ResAnalyzeResultDayDto.class);
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
}
TotalSalesStatusGrandson totalSalesStatusYear = new TotalSalesStatusGrandson();
totalSalesStatusYear.setTotal(new BigDecimal(sumTotalPrice));
resultObj.setTotalSalesStatusYear(totalSalesStatusYear);
resultObj.setUnitLabel("sample");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ResponseEntity<TotalSalesStatus> result = new ResponseEntity<TotalSalesStatus>(resultObj, headers, HttpStatus.CREATED);
return result;
}
日志
2017-06-05 13:33:48.382 [maekawa-PC-http-nio-9999-exec-1] INFO SAMPLE:[id: tenant_id:] j.c.b.b.m.r.a.TotalSalesStatusCommandService ■■UT:[createFinalResultObj3]
2017-06-05 13:33:48.382 [maekawa-PC-http-nio-9999-exec-1] INFO SAMPLE:[id: tenant_id:] j.c.b.b.m.r.a.TotalSalesStatusCommandService ■■UT:[createFinalResultObj3] ResAnalyzeMetaDto :ResAnalyzeMetaDto(startTime=2017-06-05T04:33:48.499791734Z, executeTime=2.1928, host=bb8bfd9acf04, rid=)
2017-06-05 13:33:48.382 [maekawa-PC-http-nio-9999-exec-1] INFO SAMPLE:[id: tenant_id:] j.c.b.b.m.r.a.TotalSalesStatusCommandService ■■UT:[createFinalResultObj3] ResAnalyzeResultDto:{2016-04-01={0:num=121, 0:price=5244614, 1:num=124, 1:price=6324547, 2:num=115, 2:price=5604491}, 2016-04-02={0:num=125, 0:price=6321222, 1:num=117, 1:price=5835030, 2:num=118, 2:price=5771826}, 2016-04-03={0:num=118, 0:price=5486071, 1:num=131, 1:price=6563447, 2:num=111, 2:price=5740078}, subTotal={total_2016-04-01_num=360, total_2016-04-01_price=17173652, total_2016-04-02_num=360, total_2016-04-02_price=17928078, total_2016-04-03_num=360, total_2016-04-03_price=17789596}, total={num=1080, price=52891326}}
key: 2016-04-01 value: {0:num=121, 0:price=5244614, 1:num=124, 1:price=6324547, 2:num=115, 2:price=5604491}
v.toString(): {0:num=121, 0:price=5244614, 1:num=124, 1:price=6324547, 2:num=115, 2:price=5604491}
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('0' (code 48)): was expecting double-quote to start field name
at [Source: {0:num=121, 0:price=5244614, 1:num=124, 1:price=6324547, 2:num=115, 2:price=5604491}; line: 1, column: 3]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1702)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:558)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:456)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddName(ReaderBasedJsonParser.java:1771)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:684)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3798)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2842)
at jp.co.temp.sample.management.report.api.TotalSalesStatusCommandService.lambda$createFinalResultObj3$3(TotalSalesStatusCommandService.java:636)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)