FastJSON中将Long型数据转String响应到前端

小感触 2020年01月30日 219次浏览

2020.02.07更新:

一个新的解决方式,验证可用:https://www.cnblogs.com/lvgg/p/7475140.html

Jackson解决:

如果使用的是jackson而非fastjson,使用下面的方式解决:

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

@JsonSerialize(using = ToStringSerializer.class)
private Long id;

历史解决方式:

简单说下经过:后端返回一个Long型的id字段到前端,但是前端拿到的值并不是预期那样,后来发现是因为精度问题导致了,因此想要把这类容易出现此问题的字段,全部使用String类型进行响应,这里使用的fastjson这个工具进行处理的。解决方式比较简单, 在要转换的属性上面使用注解@JSONField即可,指定这个属性要使用的系列化类即可,这里使用Long转String。@JSONField(serializeUsing= ToStringSerializer.class):

@Data
public class AppUpdateDTO implements Serializable {
    @NotNull(message = "必须指定被更新应用的ID")
    @JSONField(serializeUsing= ToStringSerializer.class)
    private Long id;
    ....
}
  • fastjson在com.alibaba.fastjson.serializer包下面提供了多种数据类型转换的注解。我们上面在注解里面指定的ToStringSerializer.class具体的实现如下:
public class ToStringSerializer implements ObjectSerializer {
    public static final ToStringSerializer instance = new ToStringSerializer();
    @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;
        }
        String strVal = object.toString();
        out.writeString(strVal);
    }
}
  • 通过以上代码我们可以知道,如果哪天需要一些自定义的转换时,我们可以自己书写相应的类(不要忘记注入)并实现ObjectSerializer接口,最后在注解里面指定我们新建的类即可。

如果很多地方都需要这种转换,那就直接配置一个全局的即可:

  • 新建一个类,继承WebMvcConfigurationSupport类,重写下面的方法,在里面指定转换规则,这里仍旧是指定将Long转换为String。
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("加载类型转换器");
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        /**
         * 序列换成json时,将所有的long变成string
         * 因为js中得数字类型不能包含所有的java long值
         */
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(jackson2HttpMessageConverter);
    }
  • 记录一个自己疏忽的点:在按照以上步骤配置之后,发现并不生效,后来发现,是因为我已经有了一个继承自WebMvcConfigurationSupport的配置类A。这个配置类是关于拦截器的,里面只是重写了addInterceptors()方法。后来我又写了一个配置类B,也是继承WebMvcConfigurationSupport,重写本文中要求的configureMessageConverters方法。A和B都是注入到容器的,后来感觉应该是只有A生效,B没生效。解决也很简单,将A和B合在一起,使用一个类就行的。