ssslinppp

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Jackson将json转换成泛型List

获取泛型类型

/**
 * 获取泛型类型
 *
 * @return
 */
protected Class<T> getGenericsType() {
    final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {
    };
    final Class<T> type = (Class<T>) typeToken.getRawType();
    return type;
}

Jackson库--json转换成泛型List

/**
 * 获取Jackson的{@code List<T>}类型
 *
 * @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<T> queryResults = mapper.readValue(jsonStr, getListType(mapper));

使用

 IGraphiteQueryTemplete<GraQueryResultSub> queryTempleteWithType = new AbstractGraphiteQueryTemplete<GraQueryResultSub>() { };
List<GraQueryResultSub> 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<T extends GraphiteQueryResult> {
    /**
     * post请求,查询Graphite数据,默认格式为:json
     *
     * @param queryParam
     * @return
     */
    List<T> 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<T extends GraphiteQueryResult> implements IGraphiteQueryTemplete<T> {
    private static final Logger logger = LoggerFactory.getLogger(GraphiteQueryTempleteBase.class);

    @Autowired
    protected RestTemplate restTemplate;
//    protected RestTemplate restTemplate = new RestTemplate();

    /**
     * 获取 Graphite 查询 post 请求体<br/>
     *
     * @param queryParam Graphite查询参数
     * @return
     */
    protected HttpEntity<MultiValueMap<String, String>> 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<String, String> bodyMap = new LinkedMultiValueMap<String, String>();
        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<MultiValueMap<String, String>> requestBody = new HttpEntity<MultiValueMap<String, String>>(bodyMap, headers);

        return requestBody;
    }

    /**
     * 获取泛型类型
     *
     * @return
     */
    protected Class<T> getGenericsType() {
        final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {
        };
        final Class<T> type = (Class<T>) typeToken.getRawType();
        return type;
    }

    /**
     * 获取Jackson的{@code List<T>}类型
     *
     * @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<T extends GraphiteQueryResult> extends GraphiteQueryTempleteBase<T> {
    private static final Logger logger = LoggerFactory.getLogger(AbstractGraphiteQueryTemplete.class);

    @Override
    public List<T> postQuery(GraphiteQueryParam queryParam) throws IOException {
        logger.info("GraphitePostQuery - Begin to graphite post query...");
        HttpEntity<MultiValueMap<String, String>> requestBody = getGraphitePostHttpEntity(queryParam);
        logger.info("GraphitePostQuery - {GraphiteQueryParam: {}, requestBody: {}}", queryParam.toString(), requestBody.toString());

        // 查询
        ResponseEntity<String> responseEntity = restTemplate.exchange(queryParam.getRenderUrl(), HttpMethod.POST, requestBody, String
                .class);
        logger.info("GraphitePostQuery - query finished, begin to convert query result");

        // 获取结果
        List<T> queryResults = null;
        if (responseEntity.getStatusCode() == HttpStatus.OK) { //返回成功
            if (!StringUtils.isEmpty(responseEntity.getBody())) {
                ObjectMapper mapper = new ObjectMapper();
                try {
//                    queryResults = (List<T>) mapper.readValue(responseEntity.getBody(), new TypeReference<List<T>>() { });
                    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查询结果转换;
 * <p>
 * <p>
 * <pre>
 *  [
 *   {
 *     "target": "10_144_202_150",
 *     "datapoints": [
 *       [
 *         1025968.9066666667,
 *         1511861400
 *       ],
 *       [
 *         254849.70666666667,
 *         1511861700
 *       ]
 *     ]
 *   },
 *   {
 *     "target": "10_144_202_151",
 *     "datapoints": [
 *       [
 *         447786.56,
 *         1511861400
 *       ],
 *       [
 *         103653.6,
 *         1511861700
 *       ]
 *     ]
 *   }
 * ]
 *  </pre>
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GraphiteQueryResult {
    private String target;
    private List<List<Object>> 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<GraQueryResultSub> queryTempleteWithType = new AbstractGraphiteQueryTemplete<GraQueryResultSub>() {
        };
        List<GraQueryResultSub> 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;
    }
}

参考

Jackson将json转换成泛型List

posted on 2017-11-29 12:44  ssslinppp  阅读(9083)  评论(0编辑  收藏  举报