Ho avuto un problema simile, ma era correlato alle relazioni bidirezionali di Hibernate. Volevo mostrare un lato della relazione e ignorare a livello di programmazione l'altro, a seconda di quale punto di vista avevo a che fare. Se non puoi farlo, finisci con le cattive StackOverflowException
s. Ad esempio, se avessi questi oggetti
public class A{
Long id;
String name;
List<B> children;
}
public class B{
Long id;
A parent;
}
Vorrei ignorare programmaticamente il parent
campo in B se guardassi A e ignorare il children
campo in A se guardassi B.
Ho iniziato a usare i mixin per farlo, ma molto rapidamente diventa orribile; hai così tante classi inutili che esistono solo per formattare i dati. Ho finito per scrivere il mio serializzatore per gestirlo in modo più pulito: https://github.com/monitorjbl/json-view .
Ti consente di specificare a livello di codice quali campi ignorare:
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")));
Consente inoltre di specificare facilmente visualizzazioni molto semplificate tramite corrispondenze di caratteri jolly:
String json = mapper.writeValueAsString(JsonView.with(list)
.onClass(A.class, match()
.exclude("*")
.include("id", "name")));
Nel mio caso originale, la necessità di visualizzazioni semplici come questa era di mostrare il minimo indispensabile sul genitore / figlio, ma è diventato utile anche per la nostra sicurezza basata sui ruoli. Viste meno privilegiate degli oggetti necessarie per restituire meno informazioni sull'oggetto.
Tutto questo proviene dal serializzatore, ma stavo usando Spring MVC nella mia app. Per far sì che gestisca correttamente questi casi, ho scritto un'integrazione che puoi inserire nelle classi di controller Spring esistenti:
@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();
}
}
Entrambi sono disponibili su Maven Central. Spero che aiuti qualcun altro là fuori, questo è un problema particolarmente brutto con Jackson che non aveva una buona soluzione per il mio caso.