Miałem podobny problem, ale był on związany z dwukierunkowymi relacjami Hibernate. Chciałem pokazać jedną stronę relacji, a programowo zignorować drugą, w zależności od tego, z jakim poglądem mam do czynienia. Jeśli nie możesz tego zrobić, skończysz z paskudnym StackOverflowException
s. Na przykład, gdybym miał te obiekty
public class A{
Long id;
String name;
List<B> children;
}
public class B{
Long id;
A parent;
}
Chciałbym programowo zignorować parent
pole w B, gdybym patrzył na A, i zignorować children
pole w A, gdybym patrzył na B.
Zacząłem używać do tego mixinów, ale to bardzo szybko staje się okropne; masz tak wiele bezużytecznych klas, które istnieją wyłącznie po to, by formatować dane. Skończyło się na napisaniu własnego serializatora, aby poradzić sobie z tym w bardziej przejrzysty sposób: https://github.com/monitorjbl/json-view .
Pozwala programowo określić, które pola mają być ignorowane:
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")));
Umożliwia także łatwe określanie bardzo uproszczonych widoków za pomocą dopasowywania symboli wieloznacznych:
String json = mapper.writeValueAsString(JsonView.with(list)
.onClass(A.class, match()
.exclude("*")
.include("id", "name")));
W moim pierwotnym przypadku potrzeba prostych poglądów, takich jak ten, polegała na pokazaniu absolutnego minimum na temat rodzica / dziecka, ale stało się również przydatne dla naszego bezpieczeństwa opartego na rolach. Mniej uprzywilejowane widoki obiektów wymagały zwrócenia mniejszej ilości informacji o obiekcie.
Wszystko to pochodzi z serializatora, ale w mojej aplikacji używałem Spring MVC. Aby poprawnie obsłużyć te przypadki, napisałem integrację, którą możesz dodać do istniejących klas kontrolerów 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();
}
}
Oba są dostępne w Maven Central. Mam nadzieję, że pomoże to komuś innemu, jest to szczególnie brzydki problem z Jacksonem, który nie miał dobrego rozwiązania dla mojej sprawy.