如何告诉杰克逊忽略我无法控制源代码的属性?


112

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

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

谢谢!

Answers:


168

您可以使用Jackson Mixins。例如:

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

与此混合

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

有了这个:

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

编辑:

多亏了注释,在Jackson 2.5+中,API发生了变化,应使用 objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)


1
如果该属性是机器生成的,并且名称中包含不受支持的字符?喜欢 '@'?JVM允许,但Java编译器不允许。杰克逊对此有解决方案吗?
2013年

3
在杰克逊2.2中,是objectMapper.addMixInAnnotations(Class<?> target, Class<?> mixinSource);
CorayThan

如何通过指定属性名称而不是getter来忽略?
Erran Morad

68

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

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

5
如果我们可以将objectMapper配置为仅忽略特定属性,那将是很好的。即报告所有新的/未知字段的异常,除了说“ myfield”。就像mapper.configure(DeserializationFeature.failOnUnknownPropertiesExcep(new String[] {"myField"}));
ms_27 '16

请注意,也可以使用以下without()方式在阅读器上进行配置:mapper.reader().without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
Drew Stephens

我强烈建议您不要使用此机制。Jackson的“严格”思维方式会导致在未知/未处理的字段上引发错误,这是其强项之一,与Java的静态类型/编译时分析性质非常吻合。最好选择不处理给定的一组忽略字段。
Per Lundberg

26

使用Java类

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

使用注释

@JsonIgnoreProperties(ignoreUnknown=true)

11

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

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

9
这种方法对我不起作用,但可以混用。序列化后,我仍然得到忽略的属性。为什么不使用Attribute()时为什么会有mixin?
埃兰·莫拉德

9

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

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

如果您有很多类都具有一个单独的“ IgnoredType getContext()”访问器(这在许多框架中都是这样),则这可能会更加方便。


5

我有一个类似的问题,但这与Hibernate的双向关系有关。我想展示这种关系的一面,而以编程方式忽略另一面,这取决于我处理的是哪种观点。如果无法做到这一点,那么您将得到讨厌的StackOverflowExceptions。例如,如果我有这些对象

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

public class B{
  Long id;
  A parent;
}

parent如果我看着A,我想以编程方式忽略B中的字段,而忽略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()
Pasupathi Rajamanickam,

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;
        }
    });

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.