【问题标题】:How can I tell jackson to ignore a property for which I don't have control over the source code?我如何告诉杰克逊忽略我无法控制源代码的属性?
【发布时间】:2011-11-17 07:12:05
【问题描述】:

长话短说,我的一个实体有一个GeometryCollection,当您调用“getBoundary”时会引发异常(为什么这是另一本书,现在让我们说这是它的工作方式)。

有没有办法告诉杰克逊不要包含那个特定的吸气剂?我知道当我拥有/控制代码时可以使用@JacksonIgnore。但情况并非如此,jackson 通过对父对象的不断序列化来结束这一点。我在杰克逊文档中看到了一个过滤选项。这是一个合理的解决方案吗?

谢谢!

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    您可以使用Jackson Mixins。例如:

    class YourClass {
      public int ignoreThis() { return 0; }    
    }
    

    有了这个 Mixin

    abstract class MixIn {
      @JsonIgnore abstract int ignoreThis(); // we don't need it!  
    }
    

    有了这个:

    objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);
    

    编辑:

    感谢 cmets,在 Jackson 2.5+ 中,API 发生了变化,应该使用 objectMapper.addMixIn(Class<?> target, Class<?> mixinSource) 调用

    【讨论】:

    • 如果属性是机器生成的并且名称中包含不受支持的字符?喜欢 '@'? JVM 允许,但 Java 编译器不允许。杰克逊对此有解决方案吗?
    • 在杰克逊 2.2 中是objectMapper.addMixInAnnotations(Class<?> target, Class<?> mixinSource);
    • 如何通过指定属性名称而不是 getter 来忽略?
    • 也适用于 mixin 类中定义的属性:@JsonIgnore private HttpClient httpClient;
    【解决方案2】:

    如果您想始终排除任何类的某些属性,您可以使用setMixInResolver 方法:

        @JsonIgnoreProperties({"id", "index", "version"})
        abstract class MixIn {
        }
    
        mapper.setMixInResolver(new ClassIntrospector.MixInResolver(){
            @Override
            public Class<?> findMixInClassFor(Class<?> cls) {
                return MixIn.class;  
            }
    
            @Override
            public ClassIntrospector.MixInResolver copy() {
                return this;
            }
        });
    

    【讨论】:

    • 唯一对我有用的东西,谢谢!
    【解决方案3】:

    使用 Java 类

    new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    

    使用注解

    @JsonIgnoreProperties(ignoreUnknown=true)
    

    【讨论】:

      【解决方案4】:

      基于注释的方法更好。但有时需要手动操作。为此,您可以使用 ObjectWriterwithout 方法。

      ObjectMapper mapper   = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
      ObjectWriter writer   = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
      String       jsonText = writer.writeValueAsString(sourceObject);
      

      【讨论】:

      • 这种方法对我不起作用,但 mixin 可以。序列化后我仍然得到忽略的属性。当我们有 withoutAttribute() 时为什么我们有 mixins?
      • "当我们有 withoutAttribute() 时,为什么我们有 mixins?" - Mixins 不能动态设置。 stackoverflow.com/a/11849523/3105386,而我们可以使用“withoutAttributes”来做到这一点。这可能是原因之一。
      • 其次,当您想忽略具有特定名称的字段并且不关心类时,使用“withoutAttribute”。 Mixin 可以帮助您更精细地定义那些需要忽略这些字段的特定类。
      • @ErranMorad 你有没有弄清楚为什么 withoutAttribute() 不起作用?
      • ObjectWriter.withoutAttribute 无法按照答案中的建议工作。 attribute 不引用输入数据的属性名称,并且从未在这样的上下文中引用,例如this comment 中所指出的。这种方法似乎是面向内部使用的,可以看到here
      【解决方案5】:

      这里还有一个好处是使用@JsonFilter。 这里有一些细节http://wiki.fasterxml.com/JacksonFeatureJsonFilter

      【讨论】:

        【解决方案6】:

        我有一个类似的问题,但它与 Hibernate 的双向关系有关。我想展示关系的一侧并以编程方式忽略另一侧,这取决于我正在处理的视图。如果你不能这样做,你最终会得到讨厌的StackOverflowExceptions。例如,如果我有这些对象

        public class A{
          Long id;
          String name;
          List<B> children;
        }
        
        public class B{
          Long id;
          A parent;
        }
        

        如果我正在查看 A,我希望以编程方式忽略 B 中的 parent 字段,如果我正在查看 B,则忽略 A 中的 children 字段。

        我开始使用 mixins 来做这件事,但很快就变得很糟糕;你有这么多无用的类,它们只是为了格式化数据而存在。我最终编写了自己的序列化程序以更简洁的方式处理这个问题:https://github.com/monitorjbl/json-view

        它允许您以编程方式指定要忽略的字段:

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(JsonView.class, new JsonViewSerializer());
        mapper.registerModule(module);
        
        List<A> list = getListOfA();
        String json = mapper.writeValueAsString(JsonView.with(list)
            .onClass(B.class, match()
                .exclude("parent")));
        

        它还允许您通过通配符匹配器轻松指定非常简化的视图:

        String json = mapper.writeValueAsString(JsonView.with(list)
            .onClass(A.class, match()
                .exclude("*")
                 .include("id", "name")));
        

        在我原来的例子中,需要像这样的简单视图是为了显示关于父/子的最低限度,但它也对我们基于角色的安全性很有用。对象的权限较低的视图需要返回较少的对象信息。

        所有这些都来自序列化程序,但我在我的应用程序中使用了 Spring MVC。为了让它正确处理这些情况,我编写了一个集成,您可以将其放入现有的 Spring 控制器类中:

        @Controller
        public class JsonController {
          private JsonResult json = JsonResult.instance();
          @Autowired
          private TestObjectService service;
        
          @RequestMapping(method = RequestMethod.GET, value = "/bean")
          @ResponseBody
          public List<TestObject> getTestObject() {
            List<TestObject> list = service.list();
        
            return json.use(JsonView.with(list)
                .onClass(TestObject.class, Match.match()
                    .exclude("int1")
                    .include("ignoredDirect")))
                .returnValue();
          }
        }
        

        两者都可以在 Maven Central 上找到。我希望它可以帮助其他人,这是杰克逊的一个特别丑陋的问题,对我的情况没有很好的解决方案。

        【讨论】:

        • Match.match() 的导入是什么?
        【解决方案7】:

        另一种可能性是,如果您想忽略所有未知属性,您可以按如下方式配置映射器:

        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        

        【讨论】:

        • 如果我们可以将 objectMapper 配置为仅忽略特定属性,那就太好了。即报告所有新/未知字段的异常,除了让我们说“myfield”。类似mapper.configure(DeserializationFeature.failOnUnknownPropertiesExcep(new String[] {"myField"}));
        • 请注意,这也可以在阅读器上使用without() 进行配置,如:mapper.reader().without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        • 我强烈建议不要使用这种机制。 Jackson 的“严格”心态,导致在未知/未处理的字段上引发错误是它的优势之一,并且与 Java 的静态类型/编译时分析性质很好地匹配。最好选择不处理一组给定的忽略字段。
        【解决方案8】:

        如前所述,混合注释在这里工作得很好。除了每个属性 @JsonIgnore 之外的另一种可能性是使用 @JsonIgnoreType 如果您有一个永远不应包含的类型(即,如果应该忽略 GeometryCollection 属性的所有实例)。然后,您可以直接添加它(如果您控制类型),也可以使用混入,例如:

        @JsonIgnoreType abstract class MixIn { }
        // and then register mix-in, either via SerializationConfig, or by using SimpleModule
        

        如果您有很多类都有一个“IgnoredType getContext()”访问器左右(许多框架都是这种情况),这会更方便

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-28
          • 1970-01-01
          • 2017-01-14
          • 2020-10-13
          • 1970-01-01
          • 2018-12-12
          • 1970-01-01
          • 2023-04-10
          相关资源
          最近更新 更多