У меня была аналогичная проблема, но она была связана с двунаправленными отношениями Hibernate. Я хотел показать одну сторону отношений и программно игнорировать другую, в зависимости от того, с какой точкой зрения я имел дело. Если вы не можете этого сделать, вы получите неприятные StackOverflowException
s. Например, если бы у меня были эти предметы
public class A{
Long id;
String name;
List<B> children;
}
public class B{
Long id;
A parent;
}
Я бы хотел программно игнорировать parent
поле в B, если бы я смотрел на A, и игнорировать children
поле в A, если бы я смотрел на B.
Я начал использовать миксины для этого, но это очень быстро становится ужасным; у вас есть так много бесполезных классов, которые существуют исключительно для форматирования данных. В итоге я написал свой собственный сериализатор, чтобы упростить эту задачу: 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. Я надеюсь, что это поможет кому-то еще, это особенно неприятная проблема с Джексоном, у которой не было хорошего решения для моего случая.