J'ai eu un problème similaire, mais il était lié aux relations bidirectionnelles d'Hibernate. Je voulais montrer un côté de la relation et ignorer l'autre par programmation, en fonction du point de vue auquel je traitais. Si vous ne pouvez pas faire cela, vous vous retrouvez avec des méchants StackOverflowException
. Par exemple, si j'avais ces objets
public class A{
Long id;
String name;
List<B> children;
}
public class B{
Long id;
A parent;
}
Je voudrais ignorer par programme le parent
champ de B si je regardais A, et ignorer le children
champ de A si je regardais B.
J'ai commencé par utiliser des mixins pour faire cela, mais cela devient très vite horrible; vous avez tellement de classes inutiles qui existent uniquement pour formater des données. J'ai fini par écrire mon propre sérialiseur pour gérer cela de manière plus propre: https://github.com/monitorjbl/json-view .
Il vous permet de spécifier par programme les champs à ignorer:
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")));
Il vous permet également de spécifier facilement des vues très simplifiées via des correspondances génériques:
String json = mapper.writeValueAsString(JsonView.with(list)
.onClass(A.class, match()
.exclude("*")
.include("id", "name")));
Dans mon cas d'origine, le besoin de vues simples comme celle-ci était de montrer le strict minimum sur le parent / enfant, mais cela est également devenu utile pour notre sécurité basée sur les rôles. Vues moins privilégiées des objets nécessaires pour renvoyer moins d'informations sur l'objet.
Tout cela provient du sérialiseur, mais j'utilisais Spring MVC dans mon application. Pour lui permettre de gérer correctement ces cas, j'ai écrit une intégration que vous pouvez ajouter aux classes de contrôleurs Spring existantes:
@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();
}
}
Les deux sont disponibles sur Maven Central. J'espère que cela aide quelqu'un d'autre, c'est un problème particulièrement laid avec Jackson qui n'avait pas de bonne solution pour mon cas.