У меня была похожая проблема, но она была связана с двунаправленными отношениями Hibernate.Я хотел показать одну сторону отношений и программно игнорировать другую, в зависимости от того, с какой точкой зрения я имел дело.Если вы не можете сделать это, вы получите неприятные StackOverflowException
с.Например, если бы у меня были эти объекты
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.Я надеюсь, что это поможет кому-то еще, это особенно уродливая проблема с Джексоном, у которой не было хорошего решения для моего случая.