webentwicklung-frage-antwort-db.com.de

Wie kann ich jackson anweisen, eine Eigenschaft zu ignorieren, für die ich keinen Einfluss auf den Quellcode habe?

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!

96
maverick

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.

141
Amir Raminfar

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);
58
laloumen

Java-Klasse verwenden

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

Verwenden von Anmerkungen

@JsonIgnoreProperties(ignoreUnknown=true)
22

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).

8
StaxMan

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);
7
Fırat KÜÇÜK

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 StackOverflowExceptions 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.

5
monitorjbl

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;
        }
    });
0
fifman

Ein weiterer guter Punkt ist die Verwendung von @JsonFilter. Einige Details hier http://wiki.fasterxml.com/JacksonFeatureJsonFilter