新增 long 集合类型的 string 转换
This commit is contained in:
@@ -0,0 +1,43 @@
|
|||||||
|
package com.zt.plat.framework.common.util.json.databind;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Long / long 数组序列化器,统一按字符串输出以规避 JS 精度问题。
|
||||||
|
*/
|
||||||
|
public class LongArraySerializer extends StdSerializer<Object> {
|
||||||
|
|
||||||
|
public static final LongArraySerializer INSTANCE = new LongArraySerializer();
|
||||||
|
|
||||||
|
private LongArraySerializer() {
|
||||||
|
super(Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||||
|
gen.writeStartArray();
|
||||||
|
if (value instanceof long[]) {
|
||||||
|
long[] array = (long[]) value;
|
||||||
|
for (long element : array) {
|
||||||
|
// 原生 long 必定有值,直接走 NumberSerializer
|
||||||
|
NumberSerializer.INSTANCE.serialize(element, gen, provider);
|
||||||
|
}
|
||||||
|
gen.writeEndArray();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long[] array = (Long[]) value;
|
||||||
|
for (Long element : array) {
|
||||||
|
if (element == null) {
|
||||||
|
provider.defaultSerializeNull(gen);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NumberSerializer.INSTANCE.serialize(element, gen, provider);
|
||||||
|
}
|
||||||
|
gen.writeEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.zt.plat.framework.common.util.json.databind;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 {@link Collection} 中的 Long 元素序列化成字符串,避免 JavaScript 精度问题。
|
||||||
|
*/
|
||||||
|
public class LongCollectionSerializer extends StdSerializer<Collection<?>> {
|
||||||
|
|
||||||
|
public static final LongCollectionSerializer INSTANCE = new LongCollectionSerializer();
|
||||||
|
|
||||||
|
private LongCollectionSerializer() {
|
||||||
|
super(TypeFactory.defaultInstance().constructCollectionType(Collection.class, Object.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(Collection<?> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||||
|
// 传入集合本身与元素数量,方便 Jackson 合理推测数组边界
|
||||||
|
gen.writeStartArray(value, value.size());
|
||||||
|
for (Object element : value) {
|
||||||
|
if (element == null) {
|
||||||
|
// 允许集合中存在 null,保持 Jackson 默认的 null 序列化行为
|
||||||
|
provider.defaultSerializeNull(gen);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 所有 Long/long 元素统一走 NumberSerializer,保证前端精度
|
||||||
|
NumberSerializer.INSTANCE.serialize((Number) element, gen, provider);
|
||||||
|
}
|
||||||
|
gen.writeEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.zt.plat.framework.common.util.json.databind;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.BeanDescription;
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||||
|
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
|
||||||
|
import com.fasterxml.jackson.databind.type.ArrayType;
|
||||||
|
import com.fasterxml.jackson.databind.type.CollectionType;
|
||||||
|
import com.fasterxml.jackson.databind.type.CollectionLikeType;
|
||||||
|
import com.fasterxml.jackson.databind.JavaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对 Long 相关集合、数组的序列化增强,确保统一走 Long 的自定义序列化逻辑。
|
||||||
|
*/
|
||||||
|
public class LongTypeSerializerModifier extends BeanSerializerModifier {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonSerializer<?> modifyCollectionSerializer(SerializationConfig config, CollectionType valueType,
|
||||||
|
BeanDescription beanDesc, JsonSerializer<?> serializer) {
|
||||||
|
// List、Set 等容器若包含 Long,则切换到 LongCollectionSerializer
|
||||||
|
return needsLongCollectionSerializer(valueType.getContentType()) ? LongCollectionSerializer.INSTANCE : serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonSerializer<?> modifyCollectionLikeSerializer(SerializationConfig config, CollectionLikeType valueType,
|
||||||
|
BeanDescription beanDesc, JsonSerializer<?> serializer) {
|
||||||
|
// 处理 CollectionLike(如 Page、Optional 等)中的 Long 元素
|
||||||
|
return needsLongCollectionSerializer(valueType.getContentType()) ? LongCollectionSerializer.INSTANCE : serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonSerializer<?> modifyArraySerializer(SerializationConfig config, ArrayType valueType,
|
||||||
|
BeanDescription beanDesc, JsonSerializer<?> serializer) {
|
||||||
|
// 针对 long[]、Long[] 两种数组使用统一的数组序列化器
|
||||||
|
Class<?> rawClass = valueType.getRawClass();
|
||||||
|
if (long[].class.equals(rawClass)) {
|
||||||
|
return LongArraySerializer.INSTANCE;
|
||||||
|
}
|
||||||
|
if (Long[].class.equals(rawClass)) {
|
||||||
|
return LongArraySerializer.INSTANCE;
|
||||||
|
}
|
||||||
|
return serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needsLongCollectionSerializer(JavaType contentType) {
|
||||||
|
if (contentType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Class<?> rawClass = contentType.getRawClass();
|
||||||
|
return Long.class.equals(rawClass) || Long.TYPE.equals(rawClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.zt.plat.gateway.jackson;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import com.zt.plat.framework.common.util.json.JsonUtils;
|
import com.zt.plat.framework.common.util.json.JsonUtils;
|
||||||
|
import com.zt.plat.framework.common.util.json.databind.LongTypeSerializerModifier;
|
||||||
import com.zt.plat.framework.common.util.json.databind.NumberSerializer;
|
import com.zt.plat.framework.common.util.json.databind.NumberSerializer;
|
||||||
import com.zt.plat.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
import com.zt.plat.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||||
import com.zt.plat.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
import com.zt.plat.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||||
@@ -39,6 +40,7 @@ public class JacksonAutoConfiguration {
|
|||||||
// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
|
// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
|
||||||
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||||
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||||
|
simpleModule.setSerializerModifier(new LongTypeSerializerModifier());
|
||||||
// 1.2 注册到 objectMapper
|
// 1.2 注册到 objectMapper
|
||||||
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user