为啥杰克逊还要序列化瞬态成员?

Posted

技术标签:

【中文标题】为啥杰克逊还要序列化瞬态成员?【英文标题】:Why jackson is serializing transient member also?为什么杰克逊还要序列化瞬态成员? 【发布时间】:2014-03-11 19:42:12 【问题描述】:

我正在使用 Jackson 2.1.4 将 POJO 序列化为 JSON,但我想忽略特定字段以使其序列化。我使用了瞬态,但它仍在序列化该元素。

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,因为我不想将我的模型与杰克逊特定的注释联系起来。只能使用瞬态来完成吗? objectmapper 上是否有任何用于可见性设置的 API?

【问题讨论】:

【参考方案1】:

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;
...

希望这会有所帮助。

【讨论】:

正如我在问题中提到的,我更喜欢一种不必将我的模型与杰克逊特定注释联系起来的方式。我不明白的一件事是为什么杰克逊要序列化甚至是临时成员?其他 API,如 Smart JSON 甚至 java 序列化程序都不会这样做。对此有任何想法吗? 我更新了我的原始答案以进一步解释问题并为您提供解决方案 - 希望对您有所帮助。 谢谢,我正在寻找第一个解决方案。现在我可以做到这一点,而不必使用所有杰克逊特定的注释。 不用担心 - 实际上还有其他一些方法可以做到这一点 - 你可以在这里查看我关于忽略某些字段的帖子:baeldung.com/jackson-ignore-properties-on-serialization - 很高兴我能提供帮助。干杯。 这是另一种方法(建议作为编辑):om.disable(MapperFeature.AUTO_DETECT_GETTERS) om.disable(MapperFeature.AUTO_DETECT_IS_GETTERS) om.enable(MapperFeature.AUTO_DETECT_FIELDS)【参考方案2】:

我无法让 cmets 在这里完成之前的响应,更改(现在)已弃用的方法 setVisibilityChecker 并为布尔值添加缺少的子句:

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

【讨论】:

【参考方案3】:

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

【讨论】:

这被证实可以在 Kotlin 版本 1.2.71 上使用 Kotlin 的 @Transient 注解。【参考方案4】:

您可以使用弹簧属性对其进行配置

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

【讨论】:

以上是关于为啥杰克逊还要序列化瞬态成员?的主要内容,如果未能解决你的问题,请参考以下文章

杰克逊:忽略getter,但不使用@JsonView

静态static 和瞬态transient关键字

为啥Java有瞬态字段?

为啥 ArrayList 使用瞬态存储?

为啥可以在java的抽象类中声明瞬态变量? [复制]

399transient关键字-瞬态关键字和400lbvalidClassExcecption异常_原理和解决方案