【问题标题】:Java spring MVC annotated custom date json serializer is being ignoredJava spring MVC注释的自定义日期json序列化程序被忽略
【发布时间】:2017-03-23 13:25:11
【问题描述】:

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

项目结构只是一个标准的 Spring MVC 设置,没什么特别的,我有一个控制器、服务和存储库使用休眠连接到 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 资源的各种不同答案,这些答案大多只是将我指向上面的代码。这里的任何帮助都会很棒,谢谢。

更新

我后来发现了一些用于 jackson ObjectMapperMappingJacksonHttpMessageConverter 的 bean 配置,它们可能会覆盖我的类注释?

请记住,我正在使用遗留代码,因此请不要在这里判断任何已弃用的用法。这是配置sn-p:

<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 而被忽略。

【问题讨论】:

  • 您能否向我们展示您希望将对象序列化为 JSON(您的控制器)的位置以及您看到的实际 JSON?
  • 我无法重现这个。请提供minimal reproducible example
  • @Sotirios Delimanolis 这是否意味着您无法通过使用域对象代码和序列化程序与具有上述类似依赖关系的标准 spring mvc 3.1 应用程序来重现该问题,或者您的意思是没有这里有足够的细节来做到这一点吗?我不想通过包含整个应用程序使问题变得过于嘈杂。你能不能假设应用程序正常工作而只专注于序列化程序方面?
  • 我无法重现意味着我采用了您在此处发布的代码,对您的配置做出了最小的假设,并尝试执行它。我得到了结果[{"dateTimeOfEvent":"Nov 9, 2016 9:33:31 AM"}],这不是你描述的。我不希望你发布你的整个申请。我希望您调试您的应用程序,直到您可以删除所有对问题没有影响的部分,然后发布minimal reproducible example
  • 有趣的是,您得到了描述“2016 年 11 月 9 日上午 9:33:31”的日期格式,因为我在示例中的格式字符串应输出“2016-11-09 09:33” :31 {您的时区}”。您是否调试过您的代码以查看它是否确实命中了 JsonSerializer?还是您刚刚获得了不同的简单日期格式?

标签: java json spring-mvc jackson


【解决方案1】:

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

ObjectMapper mapper = new ObjectMapper();
//deserialize json to object
MyDomainObject domainObject = mapper.readValue("Your json file or json string", MyDomainObject.class);

//serialize object to json string
String jsonString = mapper.mapper.writeValueAsString(domainObject);

并且日期等字段会被正确序列化

我找到了教程 Jackson Json Annotation Example,它还创建了自定义日期序列化程序。

【讨论】:

  • 我不明白这个答案的目的。如果您无法重现该问题,请标记/投票以关闭该问题。他们不是在尝试反序列化 JSON,而是在尝试将 POJO 序列化为 JSON。
  • @SotiriosDelimanolis。我遇到了问题,我想在这里显示反序列化和序列化。可能我打错字了。
【解决方案2】:

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

这是杰克逊映射器等的 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"
 }
]

【讨论】:

    猜你喜欢
    • 2015-02-24
    • 1970-01-01
    • 2019-05-14
    • 2013-05-20
    • 2020-01-23
    • 1970-01-01
    • 2012-05-19
    • 2014-10-06
    • 2014-09-20
    相关资源
    最近更新 更多