Java spring MVC注释自定义日期json序列化程序被忽略

时间:2016-11-09 16:43:51

标签: java json spring-mvc jackson

我有一个运行Spring MVC 3.1.x的Java 1.7应用程序,带有hibernate,由SQL Server 2008支持,使用Jackson 1.9.x将域对象序列化为JSON。

项目结构只是一个标准的Spring MVC设置,没什么特别的,我有一个控制器,服务和存储库使用hibernate连接到SQL Server。哦,我正在使用Maven 3.3.9进行依赖管理。

我的问题是日期字段格式不正确。从我的终点返回的数据只是将默认格式设为纪元号。

为了解决这个问题,我创建了一个自定义序列化器:

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

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

public class JsonDateSerialiser extends JsonSerializer<Date> {

    @Override
    public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
        String formattedDate = simpleDateFormat.format(date);
        jsonGenerator.writeString(formattedDate);
    }
}

然后我用类注释了我的域类getter:

import my.package.JsonDateSerialiser;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Date;

@Entity()
@Table(name = "tableName")
@XmlRootElement
@XmlAccessorType(value = XmlAccessType.PROPERTY)
public class MyDomainObject {

    @Id
    @Temporal(TemporalType.DATE)
    private Date dateTimeOfEvent;

    @JsonSerialize(using = JsonDateSerialiser.class)
    public Date getDateTimeOfEvent() {
        return dateTimeOfEvent;
    }

    public void setDateTimeOfEvent(Date dateTimeOfEvent) {
        this.dateTimeOfEvent = dateTimeOfEvent;
    }
}

但是注释被忽略了。

这是我的控制器右后方剥离(减去导入):

@Controller
@RequestMapping(value = "/some/data")
public class MyDataController {

  @Autowired
  private MyDataService myDataService;

  @RequestMapping(
        method = RequestMethod.GET,
        value = "/{eventType}",
        produces = MediaType.APPLICATION_JSON_VALUE
  )
  public @ResponseBody List<MyDomainObject> getDataForEventType(@PathVariable("eventType") String eventType){
      return myDataService.getDataForEventType(eventType);
  }

}

我试着把它放在田野里,没有任何快乐。 我尝试使用@Entity注释自定义序列化程序,但没有做任何事情。 调试自定义序列化程序时,serialize方法未命中。

我从服务中获取JSON数据,但它只有一个日期数字。

返回的JSON示例:

[
 {
    "dateTimeOfEvent": 1478701160000
 },
 {
    "dateTimeOfEvent": 1478701515000
 }
]

我还查看了堆栈溢出和其他Web资源的各种不同答案,这些答案大多只是指向我上面的代码。这里的任何帮助都会很棒,谢谢。

更新

我发现杰克逊ObjectMapperMappingJacksonHttpMessageConverter的一些bean配置可能会覆盖我的班级注释吗?

请记住我正在使用遗留代码,所以请不要在此判断任何弃用的内容。这是配置代码段:

<bean id="jaxbAnnIntrospector" class="org.codehaus.jackson.xc.JaxbAnnotationIntrospector" />
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper">
    <property name="serializationConfig.annotationIntrospector" ref="jaxbAnnIntrospector" />
    <property name="deserializationConfig.annotationIntrospector" ref="jaxbAnnIntrospector" />
</bean>

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"
              p:objectMapper-ref="jacksonObjectMapper" />
    </mvc:message-converters>
</mvc:annotation-driven>

更新:

bean配置是关键。我只需要在对象映射器中添加日期格式,并在应用程序中使用全局格式。我将使用完整的bean集添加正确的答案。我还删除了所有域类级别带注释的序列化程序,因为它们因应用程序级别bean而被忽略。

2 个答案:

答案 0 :(得分:1)

所以问题只是一个应用程序级bean配置覆盖了我的类级别注释。

这是jackson mappers等的bean配置的更新版本。请注意使用它的额外SimpleDateFormat bean和ObjectMapper dateFormat属性。

<bean id="jsonDateFromat" class="java.text.SimpleDateFormat">
    <constructor-arg value="yyyy-MM-dd HH:mm:ss z"/>
</bean>
<bean id="jaxbAnnIntrospector" class="org.codehaus.jackson.xc.JaxbAnnotationIntrospector" />
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper">
    <property name="serializationConfig.annotationIntrospector" ref="jaxbAnnIntrospector" />
    <property name="deserializationConfig.annotationIntrospector" ref="jaxbAnnIntrospector" />
    <property name="dateFormat" ref="jsonDateFromat"/>
</bean>

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"
              p:objectMapper-ref="jacksonObjectMapper" />
    </mvc:message-converters>
</mvc:annotation-driven>

我删除了所有类级别的注释,因为它们被忽略了,因为这个应用程序级别配置。

这对我来说很好,因为应用程序级配置最终会很好用,但是有一个场景需要两者都很有趣。

这是我对配置进行此更改后的JSON:

[
 {
    "dateTimeOfEvent": "2016-11-09 14:19:20 GMT"
 },
 {
    "dateTimeOfEvent": "2016-11-09 14:25:15 GMT"
 }
]

答案 1 :(得分:-1)

要解决您在此处展示的内容并不容易。但是,我想与你分享我的想法。您的序列化程序正确实现。在这里,您使用的是jackson库,这样您只需通过将json字符串序列化为java对象来进行序列化操作。我想你可以在这一步得到问题。进行序列化,你可以这样说:

// here temporary disable ajax
table.settings()[0].oFeatures.bServerSide = false;
table.settings()[0].ajax = false;

if (data.Messages.length > 1)
    table.rows.add(data.Messages.map(transformMessage)).draw();
else 
    table.row.add(transformMessage(data.Messages[0])).draw();

// here activate it again
table.settings()[0].oFeatures.bServerSide = true;
table.settings()[0].ajax = sUrlServerList;

日期和其他字段将被正确序列化

我发现教程Jackson Json Annotation Example也创建了自定义日期序列化程序。