【Json】Jackson將json轉換成泛型List


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM