[alibaba/fastjson]@JSONField(format = "yyyy-MM-dd") 无效

2025-11-12 211 views
5

@JSONField(format = "yyyy-MM-dd") private Date startTime; @JSONField(format = "yyyy-MM-dd") private Date endTime;

版本 1.2.38

回答

1

"endTime": "2017-11-04 11:10:19", "startTime": "2017-10-05 00:00:00",

2

这个问题可以修改或覆盖FastJsonHttpMessageConverter的writeInternal方法解决,另外JSONField注解应该放在getter或setter上分别表示序列化和反序列化时候的格式,放在属性上fastjson现在版本已经不再支持。修改writeInternal代码如下(分支master,无法提交,希望有老铁能联系阿里巴巴解决这个问题):

@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

    ByteArrayOutputStream outnew = new ByteArrayOutputStream();
    try {
        HttpHeaders headers = outputMessage.getHeaders();

        //获取全局配置的filter
        SerializeFilter[] globalFilters = fastJsonConfig.getSerializeFilters();
        List<SerializeFilter> allFilters = new ArrayList<SerializeFilter>(Arrays.asList(globalFilters));

        boolean isJsonp = false;

        //不知道为什么会有这行代码, 但是为了保持和原来的行为一致,还是保留下来
        Object value = strangeCodeForJackson(object);

        if (value instanceof FastJsonContainer) {
            FastJsonContainer fastJsonContainer = (FastJsonContainer) value;
            PropertyPreFilters filters = fastJsonContainer.getFilters();
            allFilters.addAll(filters.getFilters());
            value = fastJsonContainer.getValue();
        }

        //jsonp,保留对原本直接返回MappingFastJsonValue方法的支持
        //更好的方式是直接返回com.alibaba.fastjson.JSONPObject
        if (value instanceof MappingFastJsonValue) {
            isJsonp = true;
            value = ((MappingFastJsonValue) value).getValue();
        } else if (value instanceof JSONPObject) {
            if(!(((JSONPObject) value).getFunction() == null) && !("".equals(((JSONPObject) value).getFunction()))){
                isJsonp = true;
            }

        }

        int len = writePrefix(outnew, object);

        /* these codes are  repair by Frank Fan

         len += JSON.writeJSONString(outnew, //
                fastJsonConfig.getCharset(), //
                value, //
                fastJsonConfig.getSerializeConfig(), //
                //fastJsonConfig.getSerializeFilters(), //
                allFilters.toArray(new SerializeFilter[allFilters.size()]),
                fastJsonConfig.getDateFormat(), //
                JSON.DEFAULT_GENERATE_FEATURE, //
                fastJsonConfig.getSerializerFeatures());

         */

        /**
         * solve the problem that @JSONField(format = "yyyy-MM-dd") doesn't take effect 
         * after set global date format by the code " fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");"
         * 
         */
        //Frank Fan code start 
        if(JSON.DEFFAULT_DATE_FORMAT != fastJsonConfig.getDateFormat()){
            JSON.DEFFAULT_DATE_FORMAT = fastJsonConfig.getDateFormat();
        }

        String json = JSON.toJSONString(object, //
                fastJsonConfig.getSerializeConfig(), /*若是继承覆盖把这里的fastJsonConfig换成getFastJsonConfig()即可*/
                fastJsonConfig.getSerializeFilters(), //
                null, //
                JSON.DEFAULT_GENERATE_FEATURE, //
                fastJsonConfig.getSerializerFeatures());
        byte[] bytes = json.getBytes(getFastJsonConfig().getCharset());
        outnew.write(bytes);
        len += bytes.length;
        headers.setContentLength(len);
        OutputStream out = outputMessage.getBody();
        outnew.writeTo(out);
        outnew.close();
        //Frank Fan code start

        len += writeSuffix(outnew, object);

        if (isJsonp) {
            headers.setContentType(APPLICATION_JAVASCRIPT);
        }
        if (fastJsonConfig.isWriteContentLength()) {
            headers.setContentLength(len);
        }

        outnew.writeTo(outputMessage.getBody());

    } catch (JSONException ex) {
        throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
    } finally {
        outnew.close();
    }
}
1

表示也遇到这个问题

7

从1.1.X 升到1.2.38 之后,之前的注解在Date类型Field上的JSONField(format)都失效了,Date吐出去的变成 long了

0

表示最新版本(1.2.44)仍然没有解决这个问题

8
public void test_for_issue() throws Exception {
    Model model = JSON.parseObject("{\"startTime\":\"2017-11-04\",\"endTime\":\"2017-11-14\"}", Model.class);
    String text = JSON.toJSONString(model);
    assertEquals("{\"endTime\":\"2017-11-14\",\"startTime\":\"2017-11-04\"}", text);
}

public static class Model {
    @JSONField(format = "yyyy-MM-dd")
    public Date startTime;

    @JSONField(format = "yyyy-MM-dd")
    public Date endTime;
}

问题没重现

9

@wenshao 原楼主问题已解决,在#1511中。

2

我的1.2.45版本也是无效的:

@Bean
    public HttpMessageConverters fastJsonHttpMessageConverters(){
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        HttpMessageConverter<?> converter = fastConverter;
        return new HttpMessageConverters(converter);
    }
Date now = new Date();
requestModel.setTimestamp(now);

就这样简单调用了一下:

debug 结果:

3

@fengxueye 一样的问题

    @Bean
    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        fastJsonConfig.setSerializeConfig(serializeConfig);
        converter.setFastJsonConfig(fastJsonConfig);
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteBigDecimalAsPlain);
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        converter.setFastJsonConfig(fastJsonConfig);
        List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        converter.setSupportedMediaTypes(supportedMediaTypes);

        return converter;
    }

springboot中设置全局的fastjsonconfig dataformat, VO中使用@JSONField(format = "yyyy-MM-dd") 无效,还是格式化yyyy-MM-dd HH:mm:ss 格式了。

6

@wenshao 全局使用了format,字段设置的format是无效的。不知道这么设计的原因是什么? 在以下的代码里,为何不判断下format存在的话,覆写全局format?

if (object instanceof Date) {
            if ("unixtime".equals(format)) {
                long seconds = ((Date) object).getTime() / 1000L;
                out.writeInt((int) seconds);
                return;
            }
            DateFormat dateFormat = this.getDateFormat();
            if (dateFormat == null) {
                try {
                    dateFormat = new SimpleDateFormat(format, locale);
                } catch (IllegalArgumentException e) {
                    String format2 = format.replaceAll("T", "'T'");
                    dateFormat = new SimpleDateFormat(format2, locale);
                }
                dateFormat.setTimeZone(timeZone);
            }
            String text = dateFormat.format((Date) object);
            out.writeString(text);
            return;
        }

目前getDateFormat内部逻辑的内dateFormat因为设置了全局配置,导致不为空,造成无法使用传入的format。

全局配置如@zhouzx23所描述的