【问题标题】:Jackson ObjectMapper: How to omit (ignore) fields of certain type from serialization?Jackson ObjectMapper:如何从序列化中省略(忽略)某些类型的字段?
【发布时间】:2021-01-04 19:24:52
【问题描述】:

我如何告诉 Jackson ObjectMapper 从序列化中忽略某些类型(类)的字段,在我的 Object.class 的情况下?

约束:

  • 无法控制源类 - 它是第三方类
  • 被序列化的类类型预先未知 - 我猜它取消了 MixIn(s) 的资格
  • 此类字段名称预先未知

为了提供帮助,下面是一个单元测试,期望字段 objectsListobjectField 从序列化中被忽略,但它的方法不正确,它是按名称而不是类型过滤它们。

public static class FavoriteShows {
    public Simpsons favorite = new Simpsons();
    public BigBangTheory preferred = new BigBangTheory();
}

public static class Simpsons {
    public String title = "The Simpsons";

    public List<Object> objectsList = List.of("homer", "simpson");
    public Object objectField = new HashMap() {{
        put("mr", "burns");
        put("ned", "flanders");
    }};
}

public static class BigBangTheory {
    public String title = "The Big Bang Theory";

    public List<Object> objectsList = List.of("sheldon", "cooper");
    public Object objectField = new HashMap() {{
        put("leonard", "hofstadter");
        put("Raj", "koothrappali");
    }};
}

public abstract static class MyMixIn {
    @JsonIgnore
    private Object objectField;
    @JsonIgnore
    private Object objectsList;
}

@Test
public void test() throws JsonProcessingException {
    // GIVEN
    // Right solution must work for any (MixIn(s) is out of questions) Jackson annotated class
    // without its modification.
    final ObjectMapper mapper = new ObjectMapper()
            .addMixIn(Simpsons.class, MyMixIn.class)
            .addMixIn(BigBangTheory.class, MyMixIn.class);

    // WHEN
    String actual = mapper.writeValueAsString(new FavoriteShows());
    System.out.println(actual);

    // THEN
    // Expected: {"favorite":{"title":"The Simpsons"},"preferred":{"title":"The Big Bang Theory"}}
    assertThat(actual).isEqualTo("{\"favorite\":{\"title\":\"The Simpsons\"},\"preferred\":{\"title\":\"The Big Bang Theory\"}}");

}

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    其中一种方法是使用自定义AnnotationIntrospector

    class A {
    
        int three = 3;
        int four = 4;
        B b = new B();
    
        // setters + getters
    }
    
    class B {
    
        int one = 1;
        int two = 2;
    
        // setters + getters
    }
    

    忽略所有B类型的字段:

    ObjectMapper mapper = new ObjectMapper();
    mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
        @Override
        protected boolean _isIgnorable(Annotated a) {
            return super._isIgnorable(a)
                     // Ignore B.class
                     || a.getRawType() == B.class
                     // Ignore List<B>
                     || a.getType() == TypeFactory.defaultInstance()
                           .constructCollectionLikeType(List.class, B.class);
        }
    });
    
    String json = mapper.writeValueAsString(new A());
    

    【讨论】:

    • 很好的回答,非常感谢!!!我已经在您的答案中添加了如何检查List&lt;B&gt; - 这不是那么微不足道,希望对其他人有所帮助。希望你不要介意。
    【解决方案2】:

    如果您正在使用 mixins,您应该能够使用 @JsonIgnoreType 进行注释以使其忽略该类。 docs供参考Globally ignore class in Jackson

    【讨论】:

    • 嗯,它不起作用,例如:Objeck.class - 它会过滤掉我认为通过instanceof Object 的所有内容。 addMixIn(Object.class, MixInWithJsonIgnoreType.class)
    • 你真的在使用 addMixIn(Object.class, MixInWithJsonIgnoreType.class) 因为这当然会导致一切都被排除在外。您需要将 mixin 显式添加到正确的实现类中。
    • 嗯,我真的需要排除Object.class类型属性..... :(
    • 我认为您可能会感到困惑。在 Java 中所有不是原语的都是对象。如果您排除 Object,您实际上会排除几乎所有内容。可能发生的情况是属性类中的定义是 Object 但分配的类更具体,这通常在运行时确定类型时完成。您需要弄清楚在运行时需要排除它的实际类是什么。否则你需要排除属性而不是类型。
    • 一般来说,我不想过滤掉任何我想忽略的子类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    相关资源
    最近更新 更多