来自@PUT的MOXy unmarshalled bean为null,具体取决于JSON属性顺序

时间:2016-02-03 18:20:40

标签: json jersey unmarshalling moxy

我有一个不是解组的bean,但是没有错误消息 - 而是使用bean的null实例调用端点。

这是Jersey 2.22.1,带有默认的JAXB提供程序(MOXy)。

我用一个非常简单的bean重现了这个问题:

@XmlRootElement
public class Expense {
    private BigDecimal units;
    private BigDecimal unitRate;

    public BigDecimal getUnits() {
        return units;
    }
    public void setUnits(BigDecimal units) {
        this.units = units;
    }
    public BigDecimal getUnitRate() {
        return unitRate;
    }
    public void setUnitsRate(BigDecimal unitRate) {
        this.unitRate = unitRate;
    }
}

资源的PUT方法:

public class ExpenseResource {
    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public Response putExpense(Expense e) {
        if (e == null) {
            throw new BadRequestException("Failed to marshall expense object");
        }
        return TAEUtil.buildPutResponse(uriInfo, "/expenses/%d", this.expenseID);
    }

    //....
}

发送HTTP PUT时,会调用ExpenseResource.putExpense,但整个bean参数通常设置为null。我没有得到任何异常或记录错误。

它似乎取决于JSON属性及其顺序。具体来说,以下JSON unmarshall:

{  "units": null, "unitRate": null }

但是,如果我交换这两个属性,解组工作!

{  "unitRate": null, "units": null }

测试显示以下内容:

  1. 只要unitRate不是JSON的最后一个属性,Expense就会正确解组。
  2. 如果unitRate是final属性但未设置为null,则Expense unmarshalls BUT unitRate本身不会(其null)。例: {“units”:5,“unitRate”:5}

  3. 请注意,“单位”也是一个BigDecimal,但在最后一次正确解组时,并且当不为空时。但我发现这两个属性没有区别。

  4. 添加伪造的最终属性没有任何区别。

    {“units”:8,“unitRate”:null,“zzz”:“”} //失败

  5. 尽管将行为隔离到这一个字段,但我没有任何解释或解决方法。建议欢迎!

1 个答案:

答案 0 :(得分:1)

我的问题的根本原因是unitRate的setter上的拼写错误。它应该是“setUnitRate”而不是“setUnitsRate”。

通常情况下,这会导致unitRate在解组时不会被设置(正如我们在上面的测试#2中看到的那样)。简单到足以查找和修复。但是在这个版本的MOXy中似乎存在一个错误,如果JSON的最后一个属性与bean的任何属性都不匹配,并且它为null,则MOXy将为您提供null而不是您的其他有效bean。

{ "units": 1, "someBogusString": null }  // fails

{ "units": 1, "someBogusString": 0 } // succeeds

我将把它作为EclipseLink错误提交,看看他们对它的看法。