Tuve un problema similar, pero estaba relacionado con las relaciones bidireccionales de Hibernate. Quería mostrar un lado de la relación e ignorar programáticamente el otro, dependiendo de la vista con la que estuviera tratando. Si no puede hacer eso, terminará con desagradables StackOverflowException
s. Por ejemplo, si tuviera estos objetos
public class A{
Long id;
String name;
List<B> children;
}
public class B{
Long id;
A parent;
}
Me gustaría ignorar programáticamente el parent
campo en B si estuviera mirando A, e ignorar el children
campo en A si estuviera mirando B.
Empecé a usar mixins para hacer esto, pero muy rápidamente se vuelve horrible; tienes tantas clases inútiles por ahí que existen únicamente para formatear datos. Terminé escribiendo mi propio serializador para manejar esto de una manera más limpia: https://github.com/monitorjbl/json-view .
Le permite especificar mediante programación qué 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")));
También le permite especificar fácilmente vistas muy simplificadas a través de comparadores de comodines:
String json = mapper.writeValueAsString(JsonView.with(list)
.onClass(A.class, match()
.exclude("*")
.include("id", "name")));
En mi caso original, la necesidad de vistas simples como esta era mostrar lo mínimo sobre el padre / hijo, pero también se volvió útil para nuestra seguridad basada en roles. Se necesitaban vistas menos privilegiadas de los objetos para devolver menos información sobre el objeto.
Todo esto proviene del serializador, pero estaba usando Spring MVC en mi aplicación. Para que maneje correctamente estos casos, escribí una integración que puede incluir en las clases de controladores 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án disponibles en Maven Central. Espero que ayude a alguien más, este es un problema particularmente feo con Jackson que no tuvo una buena solución para mi caso.