杰克逊2.16.1奇怪的行为

问题描述 投票:0回答:1

我已将应用程序从 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日期(以纳秒为单位)。

有任何意见或建议欢迎留言。

java jackson jax-rs
1个回答
0
投票

经过大量测试后我发现了问题。

一开始,我没有正确标记 POJO 对象。一旦符号正确但不起作用,我尝试使用自定义序列化器。

单个对象很好,但列表或数组就不那么幸运了。

几分钟前我发现了问题。我正在使用助手来压缩输出。因此,即使我返回一个 JSON 对象,它也不会被 JSON-B 处理。 经验教训:压缩是在应用格式之前执行的。

GZIPStreamingOutput gzso = new GZIPStreamingOutput(aa); rb = Response.ok().entity(gzso).variant(new Variant(MediaType.APPLICATION_JSON_TYPE, Locale.getDefault(), "gzip"));

我过去没有遇到过这个问题,因为不需要格式化。

© www.soinside.com 2019 - 2024. All rights reserved.