强制杰克逊在没有 JsonIgnore 的情况下忽略 isEmpty

Posted

技术标签:

【中文标题】强制杰克逊在没有 JsonIgnore 的情况下忽略 isEmpty【英文标题】:Force Jackson to ignore isEmpty without JsonIgnore 【发布时间】:2014-09-30 22:09:16 【问题描述】:

我在 JAX-RS 环境中使用 Jackson 和 Jersey,并引用了一个外部库,我对它的影响有限。从这个外部库中,我使用了一些 dataholder/-model 作为返回类型,它有一个与 String.isEmpty()

相当的 isEmpty() 方法

虽然序列化不是问题,但反序列化会导致以下异常,因为数据模型没有 setEmpty() 方法,Jackson 将 isEmpty() 方法解释为名为 empty 的字段。

Unrecognized field "empty" (class de.unirostock.sems.cbarchive.meta.omex.VCard), not marked as ignorable (4 known properties: "givenName", "organization", "email", "familyName"])
at [Source: org.glassfish.jersey.message.internal.EntityInputStream@36082d97; line: 1, column: 369]

@JsonIgnore 添加到外部库不是一种选择,因为这会导致巨大的开销,而且我更愿意不将数据持有者封装到另一个数据持有者中,而只是委托方法或在 javascript 中过滤字段。

还有其他可能迫使杰克逊忽略这个“字段”吗?

【问题讨论】:

另见this、this和this。 【参考方案1】:

您可以使用Jackson's MixIn Annotations。 它允许您覆盖默认的类配置。 通过这种方式,您可以在不修改您正在使用的外部库的情况下使用@JsonIgnore

在您的示例中: 你有这个第三方类de.unirostock.sems.cbarchive.meta.omex.VCard,你希望杰克逊忽略这个空属性。

声明一个 MixIn 类或接口:

public interface VCardMixIn 
    @JsonIgnore
    boolean isEmpty();

然后在您的 Jackson 的 ObjectMapper 配置中:

objectMapper.getDeserializationConfig().addMixInAnnotations(VCard.class, VCardMixIn.class)

【讨论】:

好答案。也可以在 mixin 类型上使用 @JsonIgnoreProperties(ignoreUnknown=true) 感谢您的回复! MixIn 类型看起来与我正在寻找的想法完全一样,但是通过在非 Spring 环境中使用 Jersey,我不知道如何修改/访问 Jackson ObjectMapper。为 ObjectMapper 创建自定义 ContextResolver 是否正确? 我从来没有用过Jackson 和Jersey,所以我不知道。但我想无论如何都可以访问ObjectMapper 并对其进行自定义。也许this link 可以提供帮助。 是的,我现在实现了一个自定义 ContextResolver 并使用 MixIn 注释。我将此答案标记为有效。 这看起来像是一个仅链接的答案(链接断开)。使用该名称,我可以通过 Google 搜索到 this post,但理想的答案是独立的,实际上不需要链接来回答 OP 的问题。【参考方案2】:

假设您使用的是ObjectMapper,您可以将其配置为全局忽略未知属性。

ObjectMapper om = new ObjectMapper();
om.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

下面的简单测试说明了这一点(使用jackson-mapper-asl-1.9.10)。

public static void main(String[] args) throws Exception 
    org.codehaus.jackson.map.ObjectMapper om = new org.codehaus.jackson.map.ObjectMapper();
    om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    String json = "\"one\":\"hola mundo!\", \"empty\":\"unknown\", \"someOtherUnknown\":123";
    IgnoreUnknownTestDto dto = om.readValue(json, IgnoreUnknownTestDto.class);
    System.out.println(json+" DESERIALIZED AS "+dto);


public static class IgnoreUnknownTestDto 
    private String one;
    public String getOne() 
        return one;
    
    public void setOne(String one) 
        this.one = one;
    
    public boolean isEmpty() 
        return one == null || one.isEmpty();
    
    @Override
    public String toString() 
        return "one: '"+this.getOne()+"', empty: '"+this.isEmpty()+"'";
    

哪个输出:

"one":"hola mundo!", "empty":"unknown", "someOtherUnknown":123 DESERIALIZED AS one: 'hola mundo!', empty: 'false'

【讨论】:

对于 Jackson 2,它是 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

以上是关于强制杰克逊在没有 JsonIgnore 的情况下忽略 isEmpty的主要内容,如果未能解决你的问题,请参考以下文章

android 杰克逊 @JsonIgnore 属性

Spring @JsonIgnore 不起作用

杰克逊:我怎么能忽略getter但解析setter? [复制]

如何强制杰克逊在控制器中调用对象(dto)中所有属性的 Set 方法?

迁移到 Spring Boot 2.2.0 @JsonIgnore 不起作用

杰克逊在没有双引号的情况下序列化和反序列化对象