Java小强个人技术博客站点    手机版
当前位置: 首页 >> 开源 >> FastJson指定Long类型序列化方式

FastJson指定Long类型序列化方式

2520 开源 | 2023-12-22

fastjson 是一个性能很好的 Java 语言实现的 JSON 解析器和生成器,来自阿里巴巴的工程师开发。

主要特点:

快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson)

强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)

零依赖(没有依赖其它任何类库除了JDK)

fastjson


问题起因是因为系统内所有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


推荐您阅读更多有关于“ fastjson 序列化 Long 格式 ”的文章

上一篇:IDEA关闭属性和方法上方几个用法提示 下一篇:MyBatisPlus中MetaObjectHandler的使用

猜你喜欢

发表评论: