机台,标签配置压缩

This commit is contained in:
liuzhaotian
2024-07-09 15:39:21 +08:00
parent 6b7e30e0aa
commit b5086b450b
16 changed files with 473 additions and 42 deletions
@@ -10,13 +10,19 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
/**
* JSON 工具类
@@ -184,4 +190,245 @@ public class JsonUtils {
return JSONUtil.isTypeJSON(text);
}
/**
* 压缩
*/
public static String zipString(String unzipString) {
/**
* https://www.yiibai.com/javazip/javazip_deflater.html#article-start
* 0 ~ 9 压缩等级 低到高
* public static final int BEST_COMPRESSION = 9; 最佳压缩的压缩级别。
* public static final int BEST_SPEED = 1; 压缩级别最快的压缩。
* public static final int DEFAULT_COMPRESSION = -1; 默认压缩级别。
* public static final int DEFAULT_STRATEGY = 0; 默认压缩策略。
* public static final int DEFLATED = 8; 压缩算法的压缩方法(目前唯一支持的压缩方法)。
* public static final int FILTERED = 1; 压缩策略最适用于大部分数值较小且数据分布随机分布的数据。
* public static final int FULL_FLUSH = 3; 压缩刷新模式,用于清除所有待处理的输出并重置拆卸器。
* public static final int HUFFMAN_ONLY = 2; 仅用于霍夫曼编码的压缩策略。
* public static final int NO_COMPRESSION = 0; 不压缩的压缩级别。
* public static final int NO_FLUSH = 0; 用于实现最佳压缩结果的压缩刷新模式。
* public static final int SYNC_FLUSH = 2; 用于清除所有未决输出的压缩刷新模式; 可能会降低某些压缩算法的压缩率。
*/
//使用指定的压缩级别创建一个新的压缩器。
Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
//设置压缩输入数据。
deflater.setInput(unzipString.getBytes());
//当被调用时,表示压缩应该以输入缓冲区的当前内容结束。
deflater.finish();
final byte[] bytes = new byte[256];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256);
while (!deflater.finished()) {
//压缩输入数据并用压缩数据填充指定的缓冲区。
int length = deflater.deflate(bytes);
outputStream.write(bytes, 0, length);
}
//关闭压缩器并丢弃任何未处理的输入。
deflater.end();
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
}
/**
* 解压缩
*/
public static String unzipString(String zipString) {
byte[] decode = Base64.getDecoder().decode(zipString);
//创建一个新的解压缩器 https://www.yiibai.com/javazip/javazip_inflater.html
Inflater inflater = new Inflater();
//设置解压缩的输入数据。
inflater.setInput(decode);
final byte[] bytes = new byte[256];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256);
try {
//finished() 如果已到达压缩数据流的末尾,则返回true。
while (!inflater.finished()) {
//将字节解压缩到指定的缓冲区中。
int length = inflater.inflate(bytes);
outputStream.write(bytes, 0, length);
}
} catch (DataFormatException e) {
e.printStackTrace();
return null;
} finally {
//关闭解压缩器并丢弃任何未处理的输入。
inflater.end();
}
return outputStream.toString();
}
/*
* */
public static List<List<Object>> jsonTo2DArray(String jsonString) {
try {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonArray = objectMapper.readTree(jsonString);
Set<String> headers = new LinkedHashSet<>();
List<List<Object>> result = new ArrayList<>();
// 从数组中的所有对象收集标头
if (jsonArray.isArray()) {
for (JsonNode jsonObject : jsonArray) {
Iterator<String> fieldNames = jsonObject.fieldNames();
while (fieldNames.hasNext()) {
headers.add(fieldNames.next());
}
}
}
result.add(new ArrayList<>(headers));
// 提取行
for (JsonNode jsonObject : jsonArray) {
List<Object> row = new ArrayList<>();
for (String header : headers) {
JsonNode valueNode = jsonObject.get(header);
if (valueNode != null) {
if (valueNode.isTextual()) {
row.add(valueNode.asText());
} else if (valueNode.isInt()) {
row.add(valueNode.asInt());
} else if (valueNode.isBoolean()) {
row.add(valueNode.asBoolean());
} else if (valueNode.isDouble()) {
row.add(valueNode.asDouble());
} else if (valueNode.isArray() || valueNode.isObject() ) {
row.add(jsonTo2DArray(valueNode.toString()));
} else {
row.add(valueNode.asText());
}
} else {
row.add(null); // 处理缺少的值
}
}
result.add(row);
}
return result;
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<>();
}
}
// 抽取 json数据,不改变数据结构对应的值,只改变数据结构(参考 HPACK 算法) 实现json数据抽取
public static List<List<Object>> getData(Object object) {
String jsonString = toJsonString(object);
ObjectMapper mapper = new ObjectMapper();
try {
List<Map<String, Object>> list = mapper.readValue(jsonString, new TypeReference<>() {});
List<List<Object>> result = convertTo2DArray(list);
//
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static List<List<Object>> convertTo2DArray(List<Map<String, Object>> list) {
List<List<Object>> result = new ArrayList<>();
// Get the headers from the first map
if (list.size() > 0) {
Map<String, Object> firstMap = list.get(0);
List<Object> headers = new ArrayList<>(firstMap.keySet());
result.add(headers);
//
// Add rows
for (Map<String, Object> map : list) {
//
List<Object> row = new ArrayList<>();
for (Object header : headers) {
row.add(map.get(header));
}
result.add(row);
}
}
return result;
}
// 将所有抽取后的 json 数据都加入一个统一的数据类型中,方便前端解析哪些代码是抽取的数据,进行数据还原
@Data
@ToString(callSuper = true)
public static class ExtractedData {
List<List<Object>> extractedData;
}
public static List<List<List<Object>>> fetchData(Object obj) {
List<List<List<Object>>> data = new ArrayList<>();
try {
// 获取所有字段
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
// 跳过静态或常量字段
if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) ||
java.lang.reflect.Modifier.isFinal(field.getModifiers())) {
continue;
}
// 确保字段是可访问的
field.setAccessible(true);
// 获取字段值
Object fieldValue = field.get(obj);
// 如果字段值是一个对象,递归调用 fetchData
if (fieldValue != null && isCustomObject(fieldValue)) {
data.add(JsonUtils.jsonTo2DArray(toJsonString(fieldValue)));
fetchData(fieldValue);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
// 判断一个对象是否是自定义的类对象
private static boolean isCustomObject(Object obj) {
Class<?> clazz = obj.getClass();
// 自定义对象通常不会是 Java 的基本类型或标准库类型
// 这里可以根据具体需求进行更加复杂的判断
return !clazz.isPrimitive() &&
!clazz.getName().startsWith("java.") &&
!clazz.getName().startsWith("javax.") &&
!clazz.getName().startsWith("sun.") &&
!clazz.isAssignableFrom(Collection.class) &&
!clazz.isAssignableFrom(Map.class);
}
}