Jackson将json转换成泛型List
获取泛型类型
/**
* 获取泛型类型
*
* @return
*/
protected Class getGenericsType() {
final TypeToken typeToken = new TypeToken(getClass()) {
};
final Class type = (Class) typeToken.getRawType();
return type;
}
Jackson库--json转换成泛型List
/**
* 获取Jackson的{@code List}类型
*
* @param mapper
* @return
*/
protected JavaType getListType(ObjectMapper mapper) {
JavaType javaType = getCollectionType(mapper, ArrayList.class, getGenericsType());
return javaType;
}
/**
* 获取Jackson的集合类型
*
* @param mapper
* @param collectionClass 集合类型
* @param elementClasses 集合元素类型
* @return
*/
protected JavaType getCollectionType(ObjectMapper mapper, Class> collectionClass, Class>... elementClasses) {
return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
}
Json转换操作
ObjectMapper mapper = new ObjectMapper();
List queryResults = mapper.readValue(jsonStr, getListType(mapper));
使用
IGraphiteQueryTemplete queryTempleteWithType = new AbstractGraphiteQueryTemplete() { };
List queryResults = queryTempleteWithType.postQuery(queryParam);
完整代码
接口
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryParam;
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryResult;
import java.io.IOException;
import java.util.List;
public interface IGraphiteQueryTemplete {
/**
* post请求,查询Graphite数据,默认格式为:json
*
* @param queryParam
* @return
*/
List postQuery(GraphiteQueryParam queryParam) throws IOException;
}
抽象基类
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryParam;
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryResult;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.reflect.TypeToken;
import org.assertj.core.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
public abstract class GraphiteQueryTempleteBase implements IGraphiteQueryTemplete {
private static final Logger logger = LoggerFactory.getLogger(GraphiteQueryTempleteBase.class);
@Autowired
protected RestTemplate restTemplate;
// protected RestTemplate restTemplate = new RestTemplate();
/**
* 获取 Graphite 查询 post 请求体
*
* @param queryParam Graphite查询参数
* @return
*/
protected HttpEntity> getGraphitePostHttpEntity(GraphiteQueryParam queryParam) {
// 校验输入参数
if (Strings.isNullOrEmpty(queryParam.getTarget())) {
String message = String.format("Graphite query: target can not be null(empty),%s", queryParam.toString());
logger.error(message);
throw new IllegalArgumentException(message);
}
String targetQuery = Strings.isNullOrEmpty(queryParam.getAliasName()) ? queryParam.getTarget()
: String.format("alias(%s,\"%s\")", queryParam.getTarget(), queryParam.getAliasName());
String fromQuery = ObjectUtils.isEmpty(queryParam.getFrom()) ? queryParam.getFromDefault()
: String.valueOf((queryParam.getFrom().getTime() / 1000));
String untilQuery = ObjectUtils.isEmpty(queryParam.getUntil()) ? queryParam.getUntilDefault()
: String.valueOf((queryParam.getUntil().getTime() / 1000));
String formatQuery = Strings.isNullOrEmpty(queryParam.getFormat()) ? "json" : queryParam.getFormat();
// 测试使用,方便显示
SimpleDateFormat renderSdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
String fromForDebug = ObjectUtils.isEmpty(queryParam.getFrom()) ? queryParam.getFromDefault()
: renderSdf.format(queryParam.getFrom());
String untilForDebug = ObjectUtils.isEmpty(queryParam.getUntil()) ? queryParam.getUntilDefault()
: renderSdf.format(queryParam.getUntil());
// 设置HTTP post 请求体参数
MultiValueMap bodyMap = new LinkedMultiValueMap();
bodyMap.add("target", targetQuery);
bodyMap.add("format", formatQuery);
bodyMap.add("from", fromQuery);
bodyMap.add("until", untilQuery);
bodyMap.add("fromForDebug", fromForDebug);
bodyMap.add("untilForDebug", untilForDebug);
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// 设置 HTTP Request
HttpEntity> requestBody = new HttpEntity>(bodyMap, headers);
return requestBody;
}
/**
* 获取泛型类型
*
* @return
*/
protected Class getGenericsType() {
final TypeToken typeToken = new TypeToken(getClass()) {
};
final Class type = (Class) typeToken.getRawType();
return type;
}
/**
* 获取Jackson的{@code List}类型
*
* @param mapper
* @return
*/
protected JavaType getListType(ObjectMapper mapper) {
JavaType javaType = getCollectionType(mapper, ArrayList.class, getGenericsType());
return javaType;
}
/**
* 获取Jackson的集合类型
*
* @param mapper
* @param collectionClass 集合类型
* @param elementClasses 集合元素类型
* @return
*/
protected JavaType getCollectionType(ObjectMapper mapper, Class> collectionClass, Class>... elementClasses) {
return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
}
}
泛型实现类
import com.chinamobile.epic.graphite.query.GraphiteQueryTempleteBase;
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryParam;
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.List;
@SuppressWarnings("Duplicates")
public abstract class AbstractGraphiteQueryTemplete extends GraphiteQueryTempleteBase {
private static final Logger logger = LoggerFactory.getLogger(AbstractGraphiteQueryTemplete.class);
@Override
public List postQuery(GraphiteQueryParam queryParam) throws IOException {
logger.info("GraphitePostQuery - Begin to graphite post query...");
HttpEntity> requestBody = getGraphitePostHttpEntity(queryParam);
logger.info("GraphitePostQuery - {GraphiteQueryParam: {}, requestBody: {}}", queryParam.toString(), requestBody.toString());
// 查询
ResponseEntity responseEntity = restTemplate.exchange(queryParam.getRenderUrl(), HttpMethod.POST, requestBody, String
.class);
logger.info("GraphitePostQuery - query finished, begin to convert query result");
// 获取结果
List queryResults = null;
if (responseEntity.getStatusCode() == HttpStatus.OK) { //返回成功
if (!StringUtils.isEmpty(responseEntity.getBody())) {
ObjectMapper mapper = new ObjectMapper();
try {
// queryResults = (List) mapper.readValue(responseEntity.getBody(), new TypeReference>() { });
queryResults = mapper.readValue(responseEntity.getBody(), getListType(mapper));
} catch (IOException e) {
throw new IOException("Convert graphiteResult failed", e);
}
}
} else {//返回失败
throw new RuntimeException(String.format("Graphite post query failed,[ statusCode: %s,queryParam: %s, requestBody: %s]",
responseEntity.getStatusCode(), queryParam, requestBody));
}
logger.info("GraphitePostQuery - convert query result finish, queryResults.size(): {}", queryResults.size());
return queryResults;
}
}
model类
GraphiteQueryResult.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* Desc: Graphite查询结果, 参考:MetricDataModel.java;
* 该类的所有子类都可以用于接收Graphite查询结果转换;
*
*
*
* [
* {
* "target": "10_144_202_150",
* "datapoints": [
* [
* 1025968.9066666667,
* 1511861400
* ],
* [
* 254849.70666666667,
* 1511861700
* ]
* ]
* },
* {
* "target": "10_144_202_151",
* "datapoints": [
* [
* 447786.56,
* 1511861400
* ],
* [
* 103653.6,
* 1511861700
* ]
* ]
* }
* ]
*
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GraphiteQueryResult {
private String target;
private List> datapoints;
}
GraphiteQueryParam.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GraphiteQueryParam {
private String renderUrl; //示例:http://10.144.202.150:5000/render
private String target;
private String aliasName; //别名
/**
* Graphite支持"-10min, now, -1d"等格式的时间表示,也支持以Date的时间表示;
* 在处理from(fromDefault)/until(untilDefault)时:
* 1. 优先使用from/until;
* 2. 当from/until为null时,使用 fromDefault/untilDefault 的形式
*/
private String fromDefault = "-10min"; //默认查询最近10min数据
private String untilDefault = "now"; //以String形式表示的结束时间
private Date from; //以date形式表示的开始时间
private Date until; //以date形式表示的结束时间
private String format = "json";
}
测试类
import com.chinamobile.epic.graphite.query.IGraphiteQueryTemplete;
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryParam;
import com.chinamobile.epic.tako.model.performance.v2.graphite.GraphiteQueryResult;
import lombok.Data;
import lombok.ToString;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
public class AbstractGraphiteQueryTempleteTest {
private GraphiteQueryParam queryParam;
@Before
public void init() {
System.out.println("init...");
queryParam = new GraphiteQueryParam();
queryParam.setRenderUrl("http://10.144.202.150:5000/render");
queryParam.setTarget("groupByNode(scale(perSecond(summarize(EPIC.pm.{*}.interface.{*}.if_octets.rx, '5min', 'last', false)), 8), " +
"2, 'sum')");
}
@Test
public void postQueryWithType() throws Exception {
IGraphiteQueryTemplete queryTempleteWithType = new AbstractGraphiteQueryTemplete() {
};
List queryResults = queryTempleteWithType.postQuery(queryParam);
System.out.println(queryResults);
/**
* 输出:
* [AbstractGraphiteQueryTempleteTest.GraQueryResultSub(super=GraphiteQueryResult(target=10_144_201_1, datapoints=[[null,
* 1511925900], [null, 1511926200]]), resourceId=null),
* AbstractGraphiteQueryTempleteTest.GraQueryResultSub(super=GraphiteQueryResult(target=10_144_202_150, datapoints=[[null,
* 1511925900], [983632.64, 1511926200]]), resourceId=null),
* AbstractGraphiteQueryTempleteTest.GraQueryResultSub(super=GraphiteQueryResult(target=10_144_202_151, datapoints=[[null,
* 1511925900], [441477.6533333333, 1511926200]]), resourceId=null)]
*/
}
@Data
@ToString(callSuper = true)
public static class GraQueryResultSub extends GraphiteQueryResult {
private String resourceId;
}
}
参考