为什么Jackson也会序列化transient成员?

61

我正在使用Jackson 2.1.4将一个POJO序列化为JSON,但是我希望忽略特定字段的序列化。我使用了transient关键字,但它仍在序列化该元素。

public class TestElement {

    int x;

    private transient String y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public String getY() {
        return y;
    }

    public void setY(String y) {
        this.y = y;
    }
}

我正在进行如下序列化:

public static void main(String[] args) throws JsonProcessingException {
    TestElement testElement = new TestElement();
    testElement.setX(10);
    testElement.setY("adasd");
    ObjectMapper om = new ObjectMapper();
    String serialized = om.writeValueAsString(testElement);
    System.err.println(serialized);
}

请不要建议使用@JsonIgnore,因为我不想将我的模型与Jackson特定的注解绑定在一起。只使用transient能实现吗?ObjectMapper上是否有任何关于可见性设置的API?

4个回答

79
Jackson序列化transient成员的原因是使用getter来确定要序列化的内容,而不是成员本身-由于y有一个公共的getter,它会被序列化。 如果你想改变这个默认行为,让Jackson使用字段-只需执行以下操作:
om.setVisibilityChecker(
  om.getSerializationConfig()
    .getDefaultVisibilityChecker()
    .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
    .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
);

忽略序列化中的属性,另一种方法是直接在类上进行操作:

@JsonIgnoreProperties(value = { "y" })
public class TestElement {
...

还有一种方法是直接在字段上进行:

public class TestElement {

    @JsonIgnore
    private String y;
...

希望这能帮到你。

5
正如我在问题中提到的,我希望找到一种方法,不必将我的模型绑定到Jackson特定的注释上。但是有一件事情让我困惑,为什么Jackson甚至会序列化暂时成员?其他API(如Smart JSON甚至Java Serializer)都不这样做。你对此有什么想法吗? - Naman
3
我更新了原来的回答,进一步解释了问题并为您提供了解决方案 - 希望有所帮助。 - Eugen
谢谢,我一直在寻找第一个解决方案。现在我可以不必使用所有的Jackson特定注释来完成这个任务了。 - Naman
3
这是一种替代方法(作为编辑建议):om.disable(MapperFeature.AUTO_DETECT_GETTERS) om.disable(MapperFeature.AUTO_DETECT_IS_GETTERS) om.enable(MapperFeature.AUTO_DETECT_FIELDS) - Eugen
1
那么,如果我在这里没有漏掉什么,就没有办法让它简单地尊重短暂关键字了吗?(你想象一下它本应该自动执行的。)是啊,听起来真是太愚蠢了。 - Manius
显示剩余2条评论

47

阻止 Jackson 进行序列化和反序列化的新方法是调用 mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true)


这已经确认在Kotlin版本1.2.71上使用Kotlin的@Transient注释是有效的。 - bartonstanley
这个方法现在已经被弃用了 - 使用: JsonMapper.builder().configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true) - bbnt

9

你可以使用Spring的属性来配置它

spring.jackson.mapper.propagate-transient-marker=true

4

我无法发表评论,因此在此处补充之前的回答,更改(现在)已弃用的方法setVisibilityChecker并添加布尔值的缺失子句:

mapper.setVisibility(
    mapper.getSerializationConfig().
    getDefaultVisibilityChecker().
    withFieldVisibility(JsonAutoDetect.Visibility.ANY).
    withGetterVisibility(JsonAutoDetect.Visibility.NONE).
    withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接