Ich hatte ein ähnliches Problem, aber es hing mit den bidirektionalen Beziehungen von Hibernate zusammen. Ich wollte eine Seite der Beziehung zeigen und die andere programmgesteuert ignorieren, je nachdem, mit welcher Ansicht ich es zu tun hatte. Wenn du das nicht kannst, bekommst du böse StackOverflowException
s. Zum Beispiel, wenn ich diese Objekte hätte
public class A{
Long id;
String name;
List<B> children;
}
public class B{
Long id;
A parent;
}
Ich würde das parent
Feld in B programmgesteuert ignorieren wollen, wenn ich A betrachte, und das children
Feld in A ignorieren, wenn ich B betrachte.
Ich habe damit angefangen, Mixins zu verwenden, aber das wird sehr schnell schrecklich. Sie haben so viele nutzlose Klassen herumliegen, die nur zum Formatieren von Daten existieren. Am Ende habe ich meinen eigenen Serializer geschrieben, um dies sauberer zu handhaben: https://github.com/monitorjbl/json-view .
Hier können Sie programmgesteuert angeben, welche Felder ignoriert werden sollen:
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")));
Außerdem können Sie mithilfe von Platzhalter-Matchern ganz einfach sehr vereinfachte Ansichten angeben:
String json = mapper.writeValueAsString(JsonView.with(list)
.onClass(A.class, match()
.exclude("*")
.include("id", "name")));
In meinem ursprünglichen Fall bestand die Notwendigkeit für einfache Ansichten wie diese darin, das Nötigste über das Elternteil / Kind zu zeigen, aber es wurde auch für unsere rollenbasierte Sicherheit nützlich. Weniger privilegierte Ansichten von Objekten, die benötigt werden, um weniger Informationen über das Objekt zurückzugeben.
All dies kommt vom Serializer, aber ich habe Spring MVC in meiner App verwendet. Um diese Fälle richtig zu behandeln, habe ich eine Integration geschrieben, die Sie in vorhandene Spring-Controller-Klassen einfügen können:
@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();
}
}
Beide sind auf Maven Central verfügbar. Ich hoffe, es hilft jemand anderem da draußen. Dies ist ein besonders hässliches Problem mit Jackson, das für meinen Fall keine gute Lösung hatte.