Eu tive um problema semelhante, mas estava relacionado aos relacionamentos bidirecionais do Hibernate. Eu queria mostrar um lado do relacionamento e ignorar programaticamente o outro, dependendo de qual visão eu estava lidando. Se você não puder fazer isso, acabará com StackOverflowException
s desagradáveis . Por exemplo, se eu tivesse esses objetos
public class A{
Long id;
String name;
List<B> children;
}
public class B{
Long id;
A parent;
}
Gostaria de ignorar programaticamente o parent
campo em B se estivesse olhando para A e ignorar o children
campo em A se estivesse olhando para B.
Comecei usando mixins para fazer isso, mas rapidamente se tornou horrível; você tem tantas classes inúteis espalhadas que existem apenas para formatar dados. Acabei escrevendo meu próprio serializador para lidar com isso de uma forma mais limpa: https://github.com/monitorjbl/json-view .
Ele permite que você especifique programaticamente quais campos ignorar:
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")));
Ele também permite que você especifique facilmente visualizações muito simplificadas por meio de correspondências de curinga:
String json = mapper.writeValueAsString(JsonView.with(list)
.onClass(A.class, match()
.exclude("*")
.include("id", "name")));
No meu caso original, a necessidade de visualizações simples como essa era mostrar o mínimo sobre o pai / filho, mas também se tornou útil para nossa segurança baseada em funções. Visualizações menos privilegiadas de objetos são necessárias para retornar menos informações sobre o objeto.
Tudo isso vem do serializador, mas eu estava usando Spring MVC em meu aplicativo. Para fazer com que ele lide adequadamente com esses casos, escrevi uma integração que você pode colocar nas classes de controlador Spring existentes:
@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();
}
}
Ambos estão disponíveis no Maven Central. Espero que ajude alguém por aí, este é um problema particularmente feio com Jackson que não tinha uma boa solução para o meu caso.