一些常见好用的java工具类

1. 编码和解码(encode/decode)算法

简单理解,编码就是把信息按照一定的规则进行组织,变换消息形式的过程,所谓解码就是把收到的信息按照一定的规则进行解析,并且这个规则往往是固定的,必须是编码者和解码者事先都知道或约定好的。常见的编码手段有Base64和压缩算法。

1.1 Base64算法

Base64最早起源于HTTP协议下的数据传输,由于HTTP协议是文本协议,所以在HTTP协议下传输二进制数据需要将二进制数据转换为字符数据。然而直接转换是不行的。因为网络传输只能传输可打印字符(在ASCII码中规定,0~31、127这33个字符属于控制字符,32~126这95个字符属于可打印字符,也就是说网络传输只能传输这95个字符)。使用Base64就是将不在这些字符范围内的其他字符转换为可打印字符
具体的64位的映射关系如下图:
在这里插入图片描述
Base64算法的固定规则:因为索引最大63,所以Base64的索引最多只占6个Bit,但是ASCII码字符需要8个Bit来表示,所以,Base64按照三个一组,会把连续的3个字节变成4个字节,然后每个字节补齐高位的2个0,这样38就等于46了,也就是说,转换后的字符串理论上将要比原来的长1/3。同时Base64规定,当需要转换的字符不是3的倍数时,一律采用补0的方式凑足3的倍数。

百度百科的例子介绍很形象
转换前 10101101,10111010,01110110
转换后 00101011, 00011011 ,00101001 ,00110110
十进制 43 27 41 54
对应码表中的值 r b p 2
所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,有关MIME的RFC还有很多,如果需要详细情况请自行查找。)
第一个字节,根据源字节的第一个字节处理。
规则:源第一字节右移两位,去掉低2位,高2位补零。
既:00 + 高6位
第二个字节,根据源字节的第一个字节和第二个字节联合处理。
规则如下,第一个字节高6位去掉然后左移四位,第二个字节右移四位
即:源第一字节低2位 + 源第2字节高4位
第三个字节,根据源字节的第二个字节和第三个字节联合处理,
规则第二个字节去掉高4位并左移两位(得高6位),第三个字节右移6位并去掉高6位(得低2位),相加即可
第四个字节,规则,源第三字节去掉高2位即可
//用更接近于编程的思维来说,编码的过程是这样的:
//第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一//个目标字符。
//然后将第一个字符与0x03(00000011)进行与(&)操作并左移4位,接着第二个字符右移4位与前者相或(|),即获得第二个目标字符。
//再将第二个字符与0x0f(00001111)进行与(&)操作并左移2位,接着第三个字符右移6位与前者相或(|),获得第三个目标字符。
//最后将第三个字符与0x3f(00111111)进行与(&)操作即获得第四个目标字符。
//在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。

java使用Base64进行编码和解码:

//编码
java.util.Base64.getEncoder().encodeToString("aaaa".getBytes("UTF-8"));
//解码
byte[] decode = Base64.getDecoder().decode(encode);
//转换为String
String aaaa = new String(decode, "UTF-8")

1.2 压缩算法

压缩算法是指在不丢失信息的前提下,缩减数据量以减少存储空间,提高传输、存储和处理效率的一种技术方法。或者是按照一定的算法对数据进行重新组织,减少数据的冗余和存储的空间,在电子与通信领域也常被称为信号编码。
消息压缩的基本原理是霍夫曼树,实现上有很多种,比如常见的gzip、LZW压缩、lz4、游程编码(RLC)、snappy等等,使用过程中根据业务场景,从性能、压缩率等方向去选择合适的。
霍夫曼树和常见的压缩算法详细介绍
压缩算法比较

1.3 Java序列化和反序列化

Java序列化就是指把Java对象转换为字节序列的过程,反之,反序列化就是指把字节序列恢复为Java对象的过程。其作用就是在跨进程跨服务的数据传输过程中,进行对象状态的保存和重建。
java序列化详解

2. 常见加密算法

2.1 什么是加密算法

加密算法分对称加密和非对称加密,其中对称加密算法的加密与解密 密钥相同,非对称加密算法的加密密钥与解密 密钥不同,此外,还有一类 不需要密钥 的 散列算法。
常见的 对称加密 算法主要有 DES、3DES、AES 等,常见的 非对称算法 主要有 RSA、DSA 等,散列算法 主要有 SHA-1、MD5 等。

2.2 MD5算法

MD5 用的是 哈希函数,它的典型应用是对一段信息产生 信息摘要,以 防止被篡改。严格来说,MD5 不是一种 加密算法 而是 摘要算法。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。

java.security.MessageDigest.getInstance("MD5").digest(content);

2.3 SHA1算法

SHA1 和 MD5类似,也是一种较流行的消息摘要算法,它比 MD5 的安全性更强。对于长度小于 2 ^ 64 位的消息,SHA1 会产生一个 160 位的 消息摘要。基于 MD5、SHA1 的信息摘要特性以及 不可逆 (一般而言),可以被应用在检查 文件完整性 以及 数字签名 等场景。

java.security.MessageDigest.getInstance("SHA1").digest(content);

2.4 HMAC算法

HMAC 发送方 和 接收方 都基于 key ,利用哈希算法 (MD5、SHA1 等)计算,来传输和保存消息,这样,哪怕黑客窃取了消息,但是没有key,是 无法计算 出正确的 散列值的,这样就可以 防止数据被篡改。

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class EncryptUtil {

    public static String getBase64String(byte[] s) {
        return Base64.getEncoder().encodeToString(s);
    }

    public static byte[] hamcsha1(String data, String key) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            return mac.doFinal(data.getBytes());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

3. 计算器


import java.util.ArrayList;
import java.util.Stack;

/**
 * 计算使用util
 *
 * @author aa
 * @since 2020-11-16
 */
public class CalculatorUtil {

    /**
     * 判断是否无效的运算结果
     *
     * @param number
     * @return
     */
    public static Boolean checkDoubleAvailable(double number) {
        if (Double.isFinite(number)) {
            return true;
        }
        return false;
    }

    /**
     * 通过公示计算
     *
     * @param obj
     * @return
     */
    public static double calculator(String obj) {
        ArrayList<String> arrayList = strFormat(obj);
        ArrayList<String> result = transform(arrayList);
        Stack<Double> stack = new Stack<>();

        for (int i = 0; i < result.size(); i++) {
            String symbol = result.get(i);
            if (isDigital(symbol)) {
                //数字直接入栈
                stack.push(Double.valueOf(symbol));
            } else {
                // 处理操作符
                double num1;
                double num2;
                //取出两个数
                num1 = stack.pop();
                num2 = stack.pop();
                switch (symbol) {
                    case "+":
                        stack.push(num2 + num1);
                        break;
                    case "-":
                        stack.push(num2 - num1);
                        break;
                    case "*":
                        stack.push(num2 * num1);
                        break;
                    case "/":
                        stack.push(num2 / num1);
                        break;
                    default:
                        break;
                }
            }
        }
        return stack.pop();
    }

    /**
     * 首先对String 进行格式化 转化成ArrayList
     *
     * @param src 3*5+8;
     * @return ArrayList 3 * 5 + 8
     */
    private static ArrayList<String> strFormat(String src) {
        if (src == null || src.equals("")) {
            return null;
        }
        ArrayList<String> arrayList = new ArrayList<>();
        StringBuilder comChar = new StringBuilder();
        for (int i = 0; i < src.length(); i++) {
            char ch = src.charAt(i);
            if (ch == ' ') {
                //去除空格
                continue;
            }
            if (!Character.isDigit(ch) && ch != '.') {
                if (!comChar.toString().trim().equals("")) {
                    arrayList.add(comChar.toString().trim());
                    comChar.delete(0, comChar.length());
                }
                arrayList.add(ch + "");
                continue;
            }
            comChar.append(ch);
        }
        if (!comChar.toString().trim().equals("")) {
            arrayList.add(comChar.toString().trim());
        }
        return arrayList;
    }

    private static boolean isDigital(String symbol) {
        return !symbol.equals("+") && !symbol.equals("-")
                && !symbol.equals("*") && !symbol.equals("/")
                && !symbol.equals("(") && !symbol.equals(")");
    }

    private static int inPriority(String ch) {
        switch (ch) {
            case "+":
            case "-":
                return 2;
            case "*":
            case "/":
                return 4;
            case ")":
                return 7;
            case "(":
                return 1;
            default:
                return 0;
        }
    }

    private static int outPriority(String ch) {
        switch (ch) {
            case "+":
            case "-":
                return 3;
            case "*":
            case "/":
                return 5;
            case ")":
                return 1;
            case "(":
                return 7;
            default:
                return 0;
        }
    }

    /**
     * 中序遍历改为后续遍历
     *
     * @param arrayList
     * @return
     */
    private static ArrayList<String> transform(ArrayList<String> arrayList) {
        Stack<String> stack = new Stack<>();
        ArrayList<String> result = new ArrayList<>();
        for (int index = 0; index < arrayList.size(); index++) {
            String symbol = arrayList.get(index);
            if (isDigital(symbol)) {
                //如果是数字直接输出
                result.add(symbol);
            } else if (symbol.equals(")")) {
                String tmp;
                while (!(tmp = stack.pop()).equals("(")) {
                    // 匹配成功后停止
                    result.add(tmp);
                }
            } else {
                if (stack.isEmpty()) {
                    stack.push(symbol);
                    continue;
                }
                String tmp = stack.peek();
                while (outPriority(symbol) <= inPriority(tmp)) {
                    //优先级小于栈内优先级,一直出栈
                    result.add(tmp);
                    stack.pop();
                    if (stack.isEmpty()) {
                        break;
                    }
                    tmp = stack.peek();
                }
                stack.push(symbol);
            }
        }
        //将剩余的出栈
        while (!stack.isEmpty()) {
            result.add(stack.pop());
        }
        return result;
    }

}

4. 时间日期处理函数


import com.tencent.youshu.common.constant.ResultCode;
import com.tencent.youshu.exception.UserException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Objects;

public abstract class DateUtil {

    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String DATE_FORMAT = "yyyyMMdd";

    public static final String DATE_FORMAT1 = "yyyy-MM-dd";


    private DateUtil() {

    }

    public static String format(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        return DateFormatUtils.format(date, DEFAULT_DATE_FORMAT);
    }

    public static String format(Date date, String pattern) {
        return DateFormatUtils.format(date, pattern);
    }


    public static Date parse(String data) {
        if (StringUtils.isBlank(data)) {
            return null;
        }
        try {
            return DateUtils.parseDate(data, DEFAULT_DATE_FORMAT);
        } catch (ParseException e) {
            throw new UserException(ResultCode.INTERNAL_ERROR);
        }
    }

    public static Date parse(String data, String format) {
        if (StringUtils.isBlank(data)) {
            return null;
        }
        try {
            return DateUtils.parseDate(data, format);
        } catch (ParseException e) {
            throw new UserException(ResultCode.INTERNAL_ERROR);
        }
    }

    public static String getStringDate(Date time, String format) {
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        String dateString = formatter.format(time);
        return dateString;
    }

    public static Date plusYear(Date time, Integer year) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(time);
        calendar.add(Calendar.YEAR, year);
        return calendar.getTime();
    }

    public static Date plusDays(Date time, Integer days) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(time);
        calendar.add(Calendar.DATE, days);
        return calendar.getTime();
    }

    public static String plusDays(String time, Integer days) {
        //先转换为date
        Date parse = parse(time, DATE_FORMAT);

        //然后增加日期
        Date date = plusDays(parse, days);
        //然后转换为string
        return getStringDate(date, DATE_FORMAT);
    }

}

5. Http调用封装util


import com.google.common.collect.Maps;
import com.tencent.youshu.common.constant.ResultCode;
import com.tencent.youshu.common.constant.ResultMsg;
import com.tencent.youshu.common.dto.HttpResultDTO;
import com.tencent.youshu.exception.UserException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;

@Slf4j
public class HttpClientUtil {


    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientUtil.class);
    private static final int DEFAULT_TIMEOUT = 30000;
    private static final RequestConfig DEFAULT_REQUEST_CONFIG = RequestConfig.custom()
            .setSocketTimeout(DEFAULT_TIMEOUT)
            .setConnectionRequestTimeout(DEFAULT_TIMEOUT)
            .setConnectTimeout(DEFAULT_TIMEOUT).build();

    private static final CloseableHttpClient httpClient;

    static {
        java.security.Security.setProperty("networkaddress.cache.ttl", "0");
        ConnectionKeepAliveStrategy keepAliveStrategy = (response, context) -> {
            HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
            while (it.hasNext()) {
                HeaderElement he = it.nextElement();
                String param = he.getName();
                String value = he.getValue();
                if (value != null && param.equalsIgnoreCase("timeout")) {
                    return Long.parseLong(value) * 1000;
                }
            }
            return 60000;//如果没有约定,则默认定义时长为60s
        };


        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();

        connectionManager.setMaxTotal(3000);
        connectionManager.setDefaultMaxPerRoute(3000);//例如默认每路由最高50并发,具体依据业务来定
        httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setKeepAliveStrategy(keepAliveStrategy)
                .setDefaultRequestConfig(DEFAULT_REQUEST_CONFIG)
                .build();
    }

    private HttpClientUtil() {

    }

    public static HttpResultDTO get(String url) {
        RequestBuilder requestBuilder = RequestBuilder.get(url);
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
        return doRequest(requestBuilder.build());
    }

    public static HttpResultDTO get(String uri, Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.get(uri);
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
        return get(uri, null, params);
    }

    public static HttpResultDTO get(String uri, Map<String, String> header,
                                    Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.get(uri);
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
        setParam(params, requestBuilder);
        setHeader(header, requestBuilder);
        return doRequest(requestBuilder.build());
    }

    public static byte[] getByte(String url) {
        RequestBuilder requestBuilder = RequestBuilder.get(url);
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
        return doStreamRequest(requestBuilder.build());
    }

    public static byte[] getByte(String url, Map<String, String> header) {
        RequestBuilder requestBuilder = RequestBuilder.get(url);
        setHeader(header, requestBuilder);
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
        return doStreamRequest(requestBuilder.build());
    }

    public static HttpResultDTO delete(String uri, Map<String, String> header, Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.delete(uri);
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
        setParam(params, requestBuilder);
        setHeader(header, requestBuilder);
        return doRequest(requestBuilder.build());
    }

    public static HttpResultDTO put(String uri, Map<String, String> header, Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.put(uri).setConfig(DEFAULT_REQUEST_CONFIG);
        setHeader(header, requestBuilder);
        setParam(params, requestBuilder);
        return doRequest(requestBuilder.build());
    }

    public static HttpResultDTO postMultipart(String uri, byte[] content, Map<String, String> header,
                                              Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.put(uri).setConfig(DEFAULT_REQUEST_CONFIG);
        requestBuilder.setEntity(new ByteArrayEntity(content));
        requestBuilder.setHeader("Content-Type", ContentType.APPLICATION_OCTET_STREAM.getMimeType());
        requestBuilder.setHeader("Accept", ContentType.APPLICATION_OCTET_STREAM.getMimeType());
        setHeader(header, requestBuilder);
        setParam(params, requestBuilder);
        return doRequest(requestBuilder.build());
    }

    public static HttpResultDTO post(String uri, Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.post(uri);
        setParam(params, requestBuilder);
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
        return doRequest(requestBuilder.build());
    }

    public static HttpResultDTO postJson(String uri, Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.post(uri);
        String requestJson = JsonUtil.objectToJson(params);
        requestBuilder.setEntity(new StringEntity(requestJson, StandardCharsets.UTF_8));
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);

        HttpUriRequest request = requestBuilder.build();
        request.setHeader("Content-type", ContentType.APPLICATION_JSON.getMimeType());
        return doRequest(request);
    }

    public static HttpResultDTO postJson(String uri, Object params) {
        RequestBuilder requestBuilder = RequestBuilder.post(uri);
        requestBuilder.setEntity(new StringEntity(JsonUtil.objectToJson(params), StandardCharsets.UTF_8));
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);

        HttpUriRequest request = requestBuilder.build();
        request.setHeader("Content-type", ContentType.APPLICATION_JSON.getMimeType());
        return doRequest(request);
    }

    public static HttpResultDTO postJson(String uri, Map<String, String> headers, Map<String, Object> params) {
        RequestBuilder requestBuilder = RequestBuilder.post(uri);
        String requestJson = JsonUtil.objectToJson(params);
        requestBuilder.setEntity(new StringEntity(requestJson, StandardCharsets.UTF_8));
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);

        HttpUriRequest request = requestBuilder.build();
        for (Map.Entry<String, String> header : headers.entrySet()) {
            request.setHeader(header.getKey(), header.getValue());
        }
        request.setHeader("Content-type", ContentType.APPLICATION_JSON.getMimeType());
        return doRequest(request);
    }

    public static HttpResultDTO postJson(String uri, Map<String, String> headers, Object params) {
        RequestBuilder requestBuilder = RequestBuilder.post(uri);
        String requestJson = JsonUtil.objectToJson(params);
        requestBuilder.setEntity(new StringEntity(requestJson, StandardCharsets.UTF_8));
        requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);

        HttpUriRequest request = requestBuilder.build();
        for (Map.Entry<String, String> header : headers.entrySet()) {
            request.setHeader(header.getKey(), header.getValue());
        }
        request.setHeader("Content-type", ContentType.APPLICATION_JSON.getMimeType());
        return doRequest(request);
    }

    private static HttpResultDTO doRequest(HttpUriRequest request) {
        ResponseHandler<HttpResultDTO> responseHandler = response -> {
            HttpEntity entity = response.getEntity();
            StatusLine statusLine = response.getStatusLine();
            int status = statusLine.getStatusCode();
            Header[] headers = response.getAllHeaders();
            String body = EntityUtils.toString(entity);
            Map<String, String> headerMap = Maps.newHashMap();
            if (ArrayUtils.isNotEmpty(headers)) {
                for (Header header : headers) {
                    headerMap.put(header.getName(), header.getValue());
                }
            }
            return new HttpResultDTO(status, body, headerMap);
        };
        try {
            log.info("http request params request:[{}],responseHandler:[{}]", request, responseHandler);
            return httpClient.execute(request, responseHandler);
        } catch (IOException e) {
            String errorMsg = e.getMessage();
            LOGGER.error(errorMsg, e);
            throw new UserException(ResultCode.INTERNAL_ERROR, ResultMsg.INTERNAL_ERROR);
        }
    }

    private static byte[] doStreamRequest(HttpUriRequest request) {
        ResponseHandler<byte[]> responseHandler = response -> {
            HttpEntity entity = response.getEntity();
            InputStream inputStream = entity.getContent();
            return IOUtils.toByteArray(inputStream);
        };
        try {
            return httpClient.execute(request, responseHandler);
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            throw new UserException(ResultCode.INTERNAL_ERROR, ResultMsg.INTERNAL_ERROR);
        }
    }

    private static void setHeader(Map<String, String> headers, RequestBuilder requestBuilder) {
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> p : headers.entrySet()) {
                requestBuilder.addHeader(p.getKey(), p.getValue());
            }
        }
    }

    private static void setParam(Map<String, Object> param, RequestBuilder requestBuilder) {
        if (param != null && !param.isEmpty()) {
            for (Map.Entry<String, Object> p : param.entrySet()) {
                Object value = p.getValue();
                if (value == null) {
                    requestBuilder.addParameter(p.getKey(), null);
                    continue;
                }
                if (value instanceof Collection || value.getClass().isArray() || value instanceof Map) {
                    requestBuilder.addParameter(p.getKey(), JsonUtil.objectToJson(p.getValue()));
                } else {
                    requestBuilder.addParameter(p.getKey(), String.valueOf(p.getValue()));
                }
            }
        }
    }
}

6. 基于jackson的json处理工具类



import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * json工具类
 *
 * @author aaa
 * @since 2020-10-22
 */
public final class JsonUtil {

    private JsonUtil() {
        throw new IllegalStateException();
    }


    private static final Rfc6901Flattener rfc6901Flattener = new Rfc6901Flattener();

    private static final ObjectMapper MAPPER = new ObjectMapper();

    public static ObjectMapper getInstance() {
        return MAPPER;
    }

    static {
        // 如果json中有新增的字段并且是实体类类中不存在的,不报错
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //日期转换格式
        //MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 将jsonNode拉平成map,默认的是.链接
     *
     * @param jsonNode
     */
    public static Map<String, JsonNode> parseJsonToMap(@NonNull JsonNode jsonNode) {
        Map<String, JsonNode> apply = rfc6901Flattener.apply(jsonNode);
        return apply;
    }


    /**
     * java Bean转换为json对象
     *
     * @param data
     * @return
     */
    public static String objectToJson(Object data) {
        if (Objects.isNull(data)) {
            return null;
        }
        try {
            String result = MAPPER.writeValueAsString(data);
            return result;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * json 转JavaBean
     */
    public static <T> T jsonToBean(String jsonData, Class<T> beanType) {
        try {
            T result = MAPPER.readValue(jsonData, beanType);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * json转list
     *
     * @param jsonData
     * @param beanType
     * @param <T>
     * @return
     */
    public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
        if (StringUtils.isBlank(jsonData)) {
            return null;
        }
        try {
            List<T> resultList = MAPPER.readValue(jsonData, javaType);
            return resultList;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * json转map
     *
     * @param jsonData  原始json
     * @param keyType   map的key
     * @param valueType map的value
     * @param <K>       key的类型
     * @param <V>       value的类型
     * @return
     */
    public static <K, V> Map<K, V> jsonToMap(String jsonData, Class<K> keyType, Class<V> valueType) {

        JavaType javaType = MAPPER.getTypeFactory().constructMapType(Map.class, keyType, valueType);
        try {
            Map<K, V> resultMap = MAPPER.readValue(jsonData, javaType);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * getJsonNodeByPath
     *
     * @param json  原json数据
     * @param paths 需要取的路径地址 按照层级
     * @return JsonNode JsonNode
     */
    public static JsonNode getJsonNodeByPath(String json, String... paths) {
        JsonNode rootNode = null;
        try {
            rootNode = MAPPER.readTree(json);

            if (paths != null && paths.length > 0) {
                //一直遍历下去
                for (int i = 0; i < paths.length; i++) {
                    String path = paths[i];
                    rootNode = rootNode.path(path);
                    //如果不存在
                    if (rootNode.isMissingNode()) {
                        return null;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return rootNode;
    }


}


import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Joiner;
import lombok.NonNull;

import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Function;

/**
 * This class flatten a json object, the key pattern is defined at the following url:
 * https://tools.ietf.org/html/rfc6901
 *
 * @author aaa
 * @since 2020-08-13
 */
public final class Rfc6901Flattener
        implements Function<JsonNode, Map<String, JsonNode>>, Serializable {

    private static final String STANDARD_SEPARATOR = ".";
    private static final int DEFAULT_EXPECT_SIZE = 15;
    private static final long serialVersionUID = 501491114373294711L;

    private final int expectSize;
    private final String prefix;
    private final String separator;

    public Rfc6901Flattener(int expectSize, @NonNull String prefix, @NonNull String separator) {
        if (expectSize <= 0 || expectSize > 1000) {
            throw new IllegalArgumentException("illegal expect size: " + expectSize);
        }
        this.expectSize = expectSize;
        this.prefix = prefix;
        this.separator = separator;
    }

    public Rfc6901Flattener() {
        this(DEFAULT_EXPECT_SIZE, "props.", STANDARD_SEPARATOR);
    }

    public static String getStandardSeparator() {
        return STANDARD_SEPARATOR;
    }

    private String generateKey(Deque<String> path, StringBuilder keyBuf) {
        if (path.size() == 1) {
            return prefix.concat(path.peek());
        }
        keyBuf.setLength(0);
        Joiner.on(separator).appendTo(keyBuf.append(prefix), path.descendingIterator());
        return keyBuf.toString();
    }

    @Override
    public Map<String, JsonNode> apply(@NonNull JsonNode jsonNode) {
        Map<String, JsonNode> result = new HashMap<>(expectSize);
        iterateOverNode(result, new ArrayDeque<>(5), new StringBuilder(16), jsonNode);
        return result;
    }

    private void iterateOverObject(
            Map<String, JsonNode> map, Deque<String> stack, StringBuilder keyBuf, JsonNode target) {
        Iterator<Map.Entry<String, JsonNode>> iterator = target.fields();
        while (iterator.hasNext()) {
            Map.Entry<String, JsonNode> entry = iterator.next();
            stack.push(entry.getKey());
            iterateOverNode(map, stack, keyBuf, entry.getValue());
            stack.pop();
        }
    }

    private void iterateOverArray(
            Map<String, JsonNode> map, Deque<String> stack, StringBuilder keyBuf, JsonNode target) {

        int size = target.size();
        for (int i = 0; i < size; ++i) {
            stack.push(Integer.toString(i));
            iterateOverNode(map, stack, keyBuf, target.get(i));
            stack.pop();
        }
    }

    private void iterateOverNode(
            Map<String, JsonNode> map, Deque<String> stack, StringBuilder keyBuf, JsonNode target) {
        if (target.isObject()) {
            iterateOverObject(map, stack, keyBuf, target);
        } else if (target.isArray()) {
            iterateOverArray(map, stack, keyBuf, target);
        } else if (target.isValueNode() && !target.isNull() && !stack.isEmpty()) {
            String key = generateKey(stack, keyBuf);
            map.put(key, target);
        }
    }
}

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值