fastjson 是一个性能很好的 Java 语言实现的 JSON 解析器和生成器,来自阿里巴巴的工程师开发。
主要特点:
快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson)
强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)
零依赖(没有依赖其它任何类库除了JDK)
问题起因是因为系统内所有ID使用了注解
@TableId(value = "id", type = IdType.ASSIGN_ID)
源码解释
@Getter public enum IdType { /** * 数据库ID自增 * <p>该类型请确保数据库设置了 ID自增 否则无效</p> */ AUTO(0), /** * 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) */ NONE(1), /** * 用户输入ID * <p>该类型可以通过自己注册自动填充插件进行填充</p> */ INPUT(2), /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */ /** * 分配ID (主键类型为number或string), * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法) * * @since 3.3.0 */ ASSIGN_ID(3), /** * 分配UUID (主键类型为 string) * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-","")) */ ASSIGN_UUID(4); private final int key; IdType(int key) { this.key = key; } }
雪花算法时,数据库字段为bigint类型,对应到Java实体为Long类型,Long类型在序列化时一般是没有问题的。
我说一般没问题,是指在Java中自己转没问题,但是反给前台后,例如(1737803505039900674)就会变成(1737803505039901000)。
我用F12看返回的数据是没问题的,但是点开详细后就会发现,后面也变成000了。
为了从根解决这个问题,返回Long类型的字段时,我们要把他序列化成String类型。
有两种方式
(1)字段上指定,添加注解
@JSONField(serializeUsing = ToStringSerializer.class)
(2)全局指定,编码自定义序列化方式
import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.ObjectSerializer; import com.alibaba.fastjson.serializer.SerializeWriter; import java.io.IOException; import java.lang.reflect.Type; public class CustomLongSerializer implements ObjectSerializer { @Override public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { SerializeWriter out = serializer.out; if (object == null) { out.writeNull(); return; } // 自定义Long类型序列化逻辑 // 例如,将Long类型转为字符串输出 out.writeString(object.toString()); } }
然后指定该序列化组件
SerializeConfig.getGlobalInstance().put(Long.class, new CustomLongSerializer());
其他
如果是日期类型,要指定序列化格式方式时,字段上可以使用注解
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
延伸:
如果使用的是Jackson,配置简单一些,编写一个配置类即可
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import org.springframework.boot.autoconfigure.jackson.JacksonProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import java.math.BigDecimal; import java.math.BigInteger; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.TimeZone; /** * Jackson序列化配置 */ @Configuration public class JacksonConfig { @Primary @Bean public ObjectMapper getObjectMapper(Jackson2ObjectMapperBuilder builder, JacksonProperties jacksonProperties) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(Long.class, ToStringSerializer.instance); simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance); simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jacksonProperties.getDateFormat()); simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter)); simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter)); objectMapper.registerModule(simpleModule); objectMapper.setTimeZone(TimeZone.getDefault()); return objectMapper; } }
END
Java小强
未曾清贫难成人,不经打击老天真。
自古英雄出炼狱,从来富贵入凡尘。
发表评论: