【问题标题】:Change Jackson date formatting setting in spring data rest webmvc在 spring data rest webmvc 中更改 Jackson 日期格式设置
【发布时间】:2014-06-02 14:20:20
【问题描述】:

Lightadmin 用于时间戳字段,例如:

@Temporal(TemporalType.TIMESTAMP)
@Column(name="started_at")
Date startedAt;

不格式化它们,而是将它们显示为自纪元以来的毫秒数,例如1398940456150

当您进入 Lightadmin 编辑页面时,例如http://localhost:8080/admin/domain/user/1/edit 在另一个请求中接收到表单实际填充的值 - http://localhost:8080/admin/rest/user/1/unit/formView?_=1401699535260,它返回 JSON:

...
"startedAt" : {
    "name" : "startedAt",
    "title" : "started at timestamp",
    "value" : 1398940456150,
    "type" : "DATE",
    "persistable" : true,
    "primaryKey" : false
}
...

任务是将1398940456150 更改为例如01.05.2014 10:34:16.

根据我的调查,org.lightadmin.core.rest.DynamicRepositoryRestController.entity()是此类请求的入口点,负责生成JSON的代码在里面:org.springframework.data.rest.webmvc.RepositoryAwareMappingHttpMessageConverter.writeInternal()

try {
  mapper.writeValue(jsonGenerator, object);
} catch(IOException ex) {
  throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
}

mapperorg.codehaus.jackson.map.ObjectMapper.ObjectMapper 的一个实例,使用默认值初始化。如果可以添加这两行:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mapper.getSerializationConfig().setDateFormat(df);

它会完成这项工作,问题是如何做到这一点?

【问题讨论】:

  • 它不起作用,因为 spring data rest webmvc version 1.0.0.RELEASE 不使用MappingJacksonHttpMessageConverter,而是使用RepositoryAwareMappingHttpMessageConverter,它有自己的ObjectMapper实例。
  • 然后调整代码?
  • 你的意思是把这个小代码改动引入到spring data rest webmvc中,发布一个新版本,然后在lightadmin里面设置一个依赖到这个新创建的spring data rest webmvc版本?
  • 我不确定最好的解决方案,RespsitoryAwareHttpMessageConverter 包含对映射器的最终非注入引用,这很不像弹簧

标签: java spring spring-mvc jackson lightadmin


【解决方案1】:

我在 Github 上发布了这个修复 - 但这里是:

我通过更改 lightadmin 代码中的 DomainTypeResourceModule 类解决了这个问题。这是该类的更新源代码。可能有更好的方法来修复它 - 但这是侵入性最小的方法,它涵盖了序列化和反序列化。

package org.lightadmin.core.rest;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.deser.std.StdDeserializer;
import org.codehaus.jackson.map.module.SimpleDeserializers;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.module.SimpleSerializers;
import org.codehaus.jackson.map.ser.std.SerializerBase;
import org.springframework.hateoas.Resource;

public class DomainTypeResourceModule extends SimpleModule {

    private final DomainTypeToResourceConverter domainTypeToResourceConverter;

    public DomainTypeResourceModule(final DomainTypeToResourceConverter domainTypeToResourceConverter) {
        super("DomainTypeResourceModule", Version.unknownVersion());

        this.domainTypeToResourceConverter = domainTypeToResourceConverter;
    }

    @Override
    public void setupModule(final SetupContext context) {
        SimpleSerializers serializers = new SimpleSerializers();
        serializers.addSerializer(DomainTypeResource.class, new DomainTypeResourceSerializer());
        serializers.addSerializer(Date.class, new JsonDateSerializer());

        SimpleDeserializers deserializers = new SimpleDeserializers();
        deserializers.addDeserializer(Date.class, new JsonDateDeserializer());

        context.addDeserializers(deserializers);
        context.addSerializers(serializers);
    }

    private class DomainTypeResourceSerializer extends SerializerBase<DomainTypeResource> {

        protected DomainTypeResourceSerializer() {
            super(DomainTypeResource.class);
        }

        @Override
        public void serialize(DomainTypeResource value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
            if (null == value) {
                provider.defaultSerializeNull(jgen);
                return;
            }

            final Resource resource = domainTypeToResourceConverter.convert(value.getResource(), value.getConfigurationUnitType(), value.getFieldMetadatas());

            jgen.writeObject(resource);
        }
    }

    private class JsonDateSerializer extends SerializerBase<Date> {

        protected JsonDateSerializer() {
            super(Date.class);
        }

        @Override
        public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {

            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String formattedDate = date == null ? "" : dateFormat.format(date);

            gen.writeString(formattedDate);
        }

    }

    private class JsonDateDeserializer extends StdDeserializer<Date> {

        protected JsonDateDeserializer() {
            super(Date.class);
        }

        @Override
        public Date deserialize(JsonParser json, DeserializationContext context) throws IOException, JsonProcessingException {

            try {
                if(json.getText() != null && !"".equals(json.getText().trim())) {
                    try {
                        return new Date(Long.parseLong(json.getText()));
                    }
                    catch(NumberFormatException nex){
                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        return dateFormat.parse(json.getText());
                    }
                }
                else return null;
            }
            catch (ParseException e){
                return null;
            }
        }

    }

}

【讨论】:

    【解决方案2】:

    我不清楚这个 data-rest-webmvc 但你可以尝试注册一个 cusotm 转换器,如下所示:

    @Component
    public class DateConverter implements Converter<String, Date> {
    
    
        @Override
        public Date convert(String source) {
            return // do the conversion
        }
    }
    

    然后像这样注册:

     <bean id="conversionService"
              class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean class="com.myapp.DateConverter"/>
                </set>
            </property>
        </bean>
    

    【讨论】:

    • Lightadmin 在版本 1.0.0.RELEASE 中使用 spring data rest webmvc 没有这样的 bean - No bean named 'jacksonSerializationConfig' is defined
    • 我不知道 lightadmin 是什么,但你就是这么干的。
    • 我以前从未见过该 jar 引用,spring-mvc 将默认为正确设置的友好输出。轻管理员 = 重管理员?
    • 好像是这样,请你看看这个class的代码,这个class是由Light(/Heavy)admin使用的,看看上面的解决方案是否可以在这里应用。
    • 配置通常会自动为您设置我认为,只是检查但看起来像更改您对 objectMapper 的 bean 引用?
    【解决方案3】:

    最新的LightAdmin 1.1.0.BUILD-SNAPSHOT 版本包含扩展数据类型支持和主要错误修复,包括与时间戳相关的错误。

    请查看并随时问我任何问题。

    【讨论】:

      猜你喜欢
      • 2016-10-26
      • 1970-01-01
      • 2016-04-11
      • 1970-01-01
      • 2015-05-04
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 2014-07-08
      相关资源
      最近更新 更多