Um es kurz zu machen, eines meiner Entitäten hat eine GeometryCollection , die eine Ausnahme auslöst, wenn Sie "getBoundary" aufrufen (das ist der Grund dafür, dass es sich um ein anderes Buch handelt.
Gibt es eine Möglichkeit, Jackson zu sagen, diesen spezifischen Getter nicht zu verwenden? Ich weiß, dass ich @JacksonIgnore verwenden kann, wenn ich den Code selbst besitze/kontrolliere. Dies ist jedoch nicht der Fall. Jackson erreicht diesen Punkt durch kontinuierliche Serialisierung der übergeordneten Objekte. Ich habe eine Filteroption in der Jackson-Dokumentation gesehen. Ist das eine plausible Lösung?
Vielen Dank!
Sie können Jackson Mixins verwenden. Zum Beispiel:
class YourClass {
public int ignoreThis() { return 0; }
}
Mit diesem Mixin
abstract class MixIn {
@JsonIgnore abstract int ignoreThis(); // we don't need it!
}
Mit diesem:
objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);
Bearbeiten:
Dank der Kommentare hat sich die API mit Jackson 2.5+ geändert und sollte mit objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)
aufgerufen werden.
Eine andere Möglichkeit ist, wenn Sie alle unbekannten Eigenschaften ignorieren möchten, können Sie den Mapper wie folgt konfigurieren:
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Java-Klasse verwenden
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Verwenden von Anmerkungen
@JsonIgnoreProperties(ignoreUnknown=true)
Mix-In-Anmerkungen funktionieren hier, wie bereits erwähnt, ziemlich gut. Eine andere Möglichkeit neben per-property @JsonIgnore ist die Verwendung von @JsonIgnoreType, wenn Sie einen Typ haben, der niemals eingeschlossen werden sollte (d. H. Wenn alle Instanzen von GeometryCollection-Eigenschaften ignoriert werden sollen). Sie können es dann entweder direkt hinzufügen (wenn Sie den Typ steuern) oder das Einmischen verwenden, z.
@JsonIgnoreType abstract class MixIn { }
// and then register mix-in, either via SerializationConfig, or by using SimpleModule
Dies kann praktischer sein, wenn Sie viele Klassen haben, die alle über einen einzigen 'IgnoredType getContext ()' - Zugriffsmechanismus verfügen (dies ist bei vielen Frameworks der Fall).
Annotationsbasierter Ansatz ist besser. Manchmal ist jedoch eine manuelle Bedienung erforderlich. Zu diesem Zweck können Sie ohne Methode von ObjectWriter verwenden.
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
ObjectWriter writer = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
String jsonText = writer.writeValueAsString(sourceObject);
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 Sicht ich mich beschäftigte. Wenn Sie das nicht können, werden Sie mit StackOverflowException
s fertig. 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 möchte das parent
-Feld in B programmatisch ignorieren, wenn ich auf A schaue, und das children
-Feld in A ignorieren, wenn ich auf B schaue.
Ich habe mit Mixins angefangen, dies zu tun, aber das wird sehr schnell fürchterlich; Sie haben so viele nutzlose Klassen, die nur zum Formatieren von Daten existieren. Am Ende schrieb ich meinen eigenen Serializer, um das sauberer zu behandeln: https://github.com/monitorjbl/json-view .
Sie können 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")));
Sie können auch sehr vereinfachte Ansichten über Platzhalter-Matcher 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 absolute Minimum über das Elternteil/Kind aufzuzeigen, wurde aber 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.
Das alles kommt vom Serializer, aber ich habe Spring MVC in meiner App verwendet. Um diese Fälle richtig handhaben zu können, 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 erhältlich. Ich hoffe, es hilft jemandem da draußen. Dies ist ein besonders hässliches Problem mit Jackson, das für meinen Fall keine gute Lösung hatte.
Wenn Sie IMMER bestimmte Eigenschaften für eine Klasse ausschließen möchten, können Sie die setMixInResolver
-Methode verwenden:
@JsonIgnoreProperties({"id", "index", "version"})
abstract class MixIn {
}
mapper.setMixInResolver(new ClassIntrospector.MixInResolver(){
@Override
public Class<?> findMixInClassFor(Class<?> cls) {
return MixIn.class;
}
@Override
public ClassIntrospector.MixInResolver copy() {
return this;
}
});
Ein weiterer guter Punkt ist die Verwendung von @JsonFilter
. Einige Details hier http://wiki.fasterxml.com/JacksonFeatureJsonFilter