简单理解,编码就是把信息按照一定的规则进行组织,变换消息形式的过程,所谓解码就是把收到的信息按照一定的规则进行解析,并且这个规则往往是固定的,必须是编码者和解码者事先都知道或约定好的。常见的编码手段有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")
压缩算法是指在不丢失信息的前提下,缩减数据量以减少存储空间,提高传输、存储和处理效率的一种技术方法。或者是按照一定的算法对数据进行重新组织,减少数据的冗余和存储的空间,在电子与通信领域也常被称为信号编码。
消息压缩的基本原理是霍夫曼树,实现上有很多种,比如常见的gzip、LZW压缩、lz4、游程编码(RLC)、snappy等等,使用过程中根据业务场景,从性能、压缩率等方向去选择合适的。
霍夫曼树和常见的压缩算法详细介绍
压缩算法比较
Java序列化就是指把Java对象转换为字节序列的过程,反之,反序列化就是指把字节序列恢复为Java对象的过程。其作用就是在跨进程跨服务的数据传输过程中,进行对象状态的保存和重建。
java序列化详解
加密算法分对称加密和非对称加密,其中对称加密算法的加密与解密 密钥相同,非对称加密算法的加密密钥与解密 密钥不同,此外,还有一类 不需要密钥 的 散列算法。
常见的 对称加密 算法主要有 DES、3DES、AES 等,常见的 非对称算法 主要有 RSA、DSA 等,散列算法 主要有 SHA-1、MD5 等。
MD5 用的是 哈希函数,它的典型应用是对一段信息产生 信息摘要,以 防止被篡改。严格来说,MD5 不是一种 加密算法 而是 摘要算法。无论是多长的输入,MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。
java.security.MessageDigest.getInstance("MD5").digest(content);
SHA1 和 MD5类似,也是一种较流行的消息摘要算法,它比 MD5 的安全性更强。对于长度小于 2 ^ 64 位的消息,SHA1 会产生一个 160 位的 消息摘要。基于 MD5、SHA1 的信息摘要特性以及 不可逆 (一般而言),可以被应用在检查 文件完整性 以及 数字签名 等场景。
java.security.MessageDigest.getInstance("SHA1").digest(content);
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);
}
}
}
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 arrayList = strFormat(obj);
ArrayList result = transform(arrayList);
Stack 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 strFormat(String src) {
if (src == null || src.equals("")) {
return null;
}
ArrayList 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 transform(ArrayList arrayList) {
Stack stack = new Stack<>();
ArrayList 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;
}
}
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);
}
}
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 params) {
RequestBuilder requestBuilder = RequestBuilder.get(uri);
requestBuilder.setConfig(DEFAULT_REQUEST_CONFIG);
return get(uri, null, params);
}
public static HttpResultDTO get(String uri, Map header,
Map 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 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 header, Map 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 header, Map 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 header,
Map 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 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 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 headers, Map 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 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 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 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 responseHandler = response -> {
HttpEntity entity = response.getEntity();
StatusLine statusLine = response.getStatusLine();
int status = statusLine.getStatusCode();
Header[] headers = response.getAllHeaders();
String body = EntityUtils.toString(entity);
Map 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 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 headers, RequestBuilder requestBuilder) {
if (headers != null && !headers.isEmpty()) {
for (Map.Entry p : headers.entrySet()) {
requestBuilder.addHeader(p.getKey(), p.getValue());
}
}
}
private static void setParam(Map param, RequestBuilder requestBuilder) {
if (param != null && !param.isEmpty()) {
for (Map.Entry 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()));
}
}
}
}
}
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 parseJsonToMap(@NonNull JsonNode jsonNode) {
Map 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 jsonToBean(String jsonData, Class beanType) {
try {
T result = MAPPER.readValue(jsonData, beanType);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* json转list
*
* @param jsonData
* @param beanType
* @param
* @return
*/
public static List jsonToList(String jsonData, Class beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
if (StringUtils.isBlank(jsonData)) {
return null;
}
try {
List 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 key的类型
* @param value的类型
* @return
*/
public static Map jsonToMap(String jsonData, Class keyType, Class valueType) {
JavaType javaType = MAPPER.getTypeFactory().constructMapType(Map.class, keyType, valueType);
try {
Map 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>, 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 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 apply(@NonNull JsonNode jsonNode) {
Map result = new HashMap<>(expectSize);
iterateOverNode(result, new ArrayDeque<>(5), new StringBuilder(16), jsonNode);
return result;
}
private void iterateOverObject(
Map map, Deque stack, StringBuilder keyBuf, JsonNode target) {
Iterator> iterator = target.fields();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
stack.push(entry.getKey());
iterateOverNode(map, stack, keyBuf, entry.getValue());
stack.pop();
}
}
private void iterateOverArray(
Map map, Deque 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 map, Deque 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);
}
}
}