我有一个类似的问题,但它与 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 上找到。我希望它可以帮助其他人,这是杰克逊的一个特别丑陋的问题,对我的情况没有很好的解决方案。