我有一个运行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资源的各种不同答案,这些答案大多只是指向我上面的代码。这里的任何帮助都会很棒,谢谢。
更新
我发现杰克逊ObjectMapper
和MappingJacksonHttpMessageConverter
的一些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而被忽略。
答案 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也创建了自定义日期序列化程序。