我怎么能告诉 Jackson 忽略一个我无法控制源代码的属性呢?

长话短说,我的一个实体有一个 几何收藏,它在您调用“ getEdge”时抛出一个异常(这是另一本书的原因,现在让我们假设它是这样工作的)。

有什么办法能让我告诉杰克逊不要包括那个特定的接收器吗?我知道当我拥有/控制代码时,我可以使用@JacksonIgnore。但事实并非如此,Jackson 最终通过连续序列化父对象来达到这一点。我在 Jackson 的文档里看到过滤选项。这是个合理的解决办法吗?

谢谢!

250226 次浏览

你可以使用 杰克逊 · 米辛斯,例如:

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

编辑:

感谢评论,对于 Jackson 2.5 + ,API 已经改变了,应该用 objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)来调用

正如前面提到的,混合注释在这里工作得非常好。Per-property@JsonIgnore 之外的另一种可能性是,如果您有一个永远不应该包含的类型(例如,如果应该忽略所有 GeomeyCollection 属性的实例) ,则使用@JsonIgnoreType。然后您可以直接添加它(如果您控制类型的话) ,或者使用 mix-in,比如:

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

如果有许多类都有一个“ IgnoredType getContext ()”访问器或类似的访问器(对许多框架来说都是如此) ,那么这可能会更方便

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

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

我有一个类似的问题,但它与 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字段。

我一开始使用 Mixin 来做这件事,但是这很快就变得很糟糕; 您周围有太多无用的类,它们仅仅是为了格式化数据而存在的。最后,我编写了自己的序列化程序来以一种更干净的方式处理这个问题: 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 买到。我希望这对其他人有所帮助,这是杰克逊的一个特别丑陋的问题,对我的情况没有一个好的解决方案。

使用 Java 类

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

使用注释

@JsonIgnoreProperties(ignoreUnknown=true)

这里还有一个好处就是使用 @JsonFilter。 这里的一些细节 < href = “ https://web.archive. org/web/20170810222415/http://wiki.fasterxml.com: 80/JacksonFeatureJsonFilter”rel = “ nofollow noReferrer”> 功能: JSON Filter

基于注释的方法更好。但有时需要手动操作。为此,可以使用 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);

如果希望总是排除任何类的某些属性,可以使用 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;
}
});