У мене була подібна проблема, але вона стосувалася двонаправлених стосунків у сплячці. Я хотів показати одну сторону стосунків і програмно ігнорувати іншу, залежно від того, з якою думкою я маю справу. Якщо ви не можете цього зробити, ви закінчитеся з неприємними 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. Я сподіваюся, що це допомагає комусь іншому, це особливо негарна проблема з Джексоном, яка не мала хорошого рішення для моєї справи.