我在一个物体上有一个重载的二传手,我怎么能告诉杰克逊忽略其中一个呢?

Dan*_*lan 3 java json jersey jackson jersey-1.0

我正在使用Jersey 1.17 com.sun.jersey.api.json.POJOMappingFeature设置为true,我正在发布一个看起来像这样的对象:

import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement
public class ByteArrayWithOverloadedSetterObject {

    private byte[] data;

    public void setData(byte[] data) {
        this.data = data;
    }

    @XmlTransient
    @JsonIgnore
    public void setData(String data) {
        this.data = data.getBytes();
    }

    public byte[] getData() {
        return data;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的资源有这个方法:

@POST
@Path("postByteArrayWithOverloadedSetterObject")
public byte[] sendByteArrayWithOverloadedSetterObject(ByteArrayWithOverloadedSetterObject byteArrayWithOverloadedSetterObject) {
    if (byteArrayWithOverloadedSetterObject.getData() == null) {
        log.warn("data was null!");
    }
    return byteArrayWithOverloadedSetterObject.getData();
}
Run Code Online (Sandbox Code Playgroud)

我的客户端单元测试是这样编写的:

@Test
public void whenSendingStringDataThenGetDataBack() {
    ByteArrayWithOverloadedSetterObject byteArrayWithOverloadedSetterObject = new ByteArrayWithOverloadedSetterObject();
    byteArrayWithOverloadedSetterObject.setData("foobar");
    byte[] data = new AuthClient().postJaxbToUrl(RestApiUriBuilder.TEST_REST_PATH + "/postByteArrayWithOverloadedSetterObject", byteArrayWithOverloadedSetterObject, byte[].class);
    assertNotNull(data);
}

@Test
public void whenSendingByteDataThenGetDataBack() {
    ByteArrayWithOverloadedSetterObject byteArrayWithOverloadedSetterObject = new ByteArrayWithOverloadedSetterObject();
    byteArrayWithOverloadedSetterObject.setData(new byte[]{0, 1, 1, 0});
    byte[] data = new AuthClient().postJaxbToUrl(RestApiUriBuilder.TEST_REST_PATH + "/postByteArrayWithOverloadedSetterObject", byteArrayWithOverloadedSetterObject, byte[].class);
    assertNotNull(data);
}
Run Code Online (Sandbox Code Playgroud)

这两个测试都失败了,消息显示"postByteArrayWithOverloadedSetterObject返回的响应状态为204 No Content",服务器正在记录"data was null!" 为每个人.为什么不通过线路对字节数组数据进行序列化?我发送这个作为JSON.

如果我注释掉@XmlTransient/ @JsonIgnore注释,我会收到此错误:"java.lang.RuntimeException:属性"data""的冲突setter定义.

在我的实际情况中,我无法轻易修改API ByteArrayWithOverloadedSetterObject.但由于这只是一个测试,我可以看到,如果我重命名第二个setter并且对象变成了这个,那么事情就能正常工作:

import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement
public class ByteArrayWithOverloadedSetterObject {

    private byte[] data;

    public void setData(byte[] data) {
        this.data = data;
    }

    @XmlTransient
    @JsonIgnore
    public void setData2(String data) {  //RENAME HERE.  Now tests pass.
        this.data = data.getBytes();
    }

    public byte[] getData() {
        return data;
    }
}
Run Code Online (Sandbox Code Playgroud)

由于我无法更改API ByteArrayWithOverloadedSetterObject,还有其他工作吗?

Dan*_*lan 5

这是解决方案:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement
public class ByteArrayWithOverloadedSetterObject {

    private byte[] data;

    @JsonProperty //I ADDED THIS
    public void setData(byte[] data) {
        this.data = data;
    }

    @XmlTransient
    @JsonIgnore
    public void setData(String data) {
        this.data = data.getBytes();
    }

    public byte[] getData() {
        return data;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我的测试通过.

  • 这里有相当多的历史; 在1.8之前,杰克逊实际上没有结合注释,所有的访问者都有单独的处理.这适用于某些用例,但对于许多其他用户来说很麻烦,并且与JAXB处理事物的方式不同.所以我同意这里的行为并不直观,但实际上很难找到实际适用于各种不同情况的可靠规则. (2认同)