我已将应用程序从 Java 8 和 Jackson 2.9 迁移到 Java 11 (Jakarta 10.0) 和 Jackson 2.16。该应用程序在 Open Liberty 上运行。 我发现了一个奇怪的行为,我不知道如何解决。我有一段从数据库检索信息的代码。这段代码用于两个不同的 REST 调用,它们返回一个元素或完整的元素列表。
public List<Assessment> getAssessments() throws Exception {
StringBuffer sb = getAssessmentsQuery();
return doAssessments(sb.toString(), new Object[] {});
}
public Assessment getAssessment(String id) throws Exception {
Assessment a = null;
StringBuffer sb = getAssessmentsQuery();
sb.append("AND F.ID=?");
List<Assessment> aa = doAssessments(sb.toString(),new String[] {id});
if (aa!=null && aa.size()>0) {
a = aa.get(0);
}
return a;
}
所以检索信息的代码是完全相同的。 REST 调用的实现方式如下:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAssessments() {
ResponseBuilder rb = Response.serverError();
try {
DB2Assessments dba = new DB2Assessments();
List<Assessment> aa = dba.getAssessments();
GZIPStreamingOutput gzso = new GZIPStreamingOutput(aa);
rb = Response.ok().entity(gzso).
variant(new Variant(MediaType.APPLICATION_JSON_TYPE,
Locale.getDefault(), "gzip"));
} catch (Exception e) {
rb.entity(e.getMessage());
}
return rb.build();
}
@GET
@Path ("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getAssessment(@PathParam("id") String id) {
ResponseBuilder rb = Response.serverError();
try {
DB2Assessments dba = new DB2Assessments();
Assessment a = dba.getAssessment(id);
if (a==null) {
rb = Response.status(404);
} else {
rb = Response.ok().entity(a);
}
} catch (Exception e) {
rb.entity(e.getMessage());
}
return rb.build();
}
每次调用的响应结果都不同。显然,一个是数组,另一个是单个对象。但字段名称和格式不同。
单个对象:
对象数组:
如您所见,单个对象(日期)的 completed 字段已被格式化为 yyyy-mm-dd 字符串 ,结尾为 Z。但在对象数组中,数据以纳秒为单位。 此外,uname字段具有不同的大小写。
实现Assessment对象的POJO类是相同的。为了完整起见,我将把它放在这里。
public class Assessment extends Base {
private Hashtable<String, Object> properties;
private String uName;
private String quarter;
private int year;
private Date completed;
private String status;
public Document() {
properties = new Hashtable<String, Object>();
}
public String getProperty(String key) {
return (String)properties.getOrDefault(key,"");
}
public Integer getNumProperty(String key) {
return (Integer)properties.getOrDefault(key,0);
}
public void setProperty(String key, Object value) {
if (value!=null) {
properties.put(key, value);
}
}
public Hashtable<String, Object> getProperties() {
return properties;
}
public void setProperties(Hashtable<String, Object> properties) {
this.properties = properties;
}
public String getUName() {
return uName;
}
public void setUName(String uName) {
this.uName = uName;
}
public String getQuarter() {
return quarter;
}
public void setQuarter(String quarter) {
this.quarter = quarter;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public Date getCompleted() {
return completed;
}
public void setCompleted(Date completed) {
this.completed = completed;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getPeriod() {
return year+"/"+quarter;
}
不仅代码相同。这个应用程序已经在旧平台上运行了几年。
是的,我知道 Jackson 有转换器和格式化程序......但为什么行为不一致?
有什么想法/意见/建议吗?
提前致谢!
更新2024-02-13
我发现雅加达没有使用杰克逊。事实上,JavaEE7 也没有使用 Jackson。 JavaEE7 使用 Apache CXF 进行序列化,Jakarta 使用 RESTEasy。所需的注释现在是由 Jsonb 提供的注释(@JsonbProperty 而不是 Jackson 的 @JsonProperty/@JsonGetter/@JsonSetter)。
所以我的 POJO 现在是:
@JsonbProperty("uname")
private String uName;
@JsonbDateFormat("yyyy-MM-dd")
private Date completed;
@JsonbProperty("uname")
public String getUName() {
return uName;
}
public void setUName(String uName) {
this.uName = uName;
}
@JsonbDateFormat("yyyy-MM-dd")
public Date getCompleted() {
return completed;
}
public void setCompleted(Date completed) {
this.completed = completed;
}
这解决了单个对象的问题。但是当返回数组时,注释被忽略,我仍然得到我的completed日期(以纳秒为单位)。
有任何意见或建议欢迎留言。
经过大量测试后我发现了问题。
一开始,我没有正确标记 POJO 对象。一旦符号正确但不起作用,我尝试使用自定义序列化器。
单个对象很好,但列表或数组就不那么幸运了。
几分钟前我发现了问题。我正在使用助手来压缩输出。因此,即使我返回一个 JSON 对象,它也不会被 JSON-B 处理。 经验教训:压缩是在应用格式之前执行的。
GZIPStreamingOutput gzso = new GZIPStreamingOutput(aa); rb = Response.ok().entity(gzso).variant(new Variant(MediaType.APPLICATION_JSON_TYPE, Locale.getDefault(), "gzip"));
我过去没有遇到过这个问题,因为不需要格式化。