Frage

In dem folgenden Jackson / Java-Code, die Objekte in JSON serialisiert, erhalte ich diese:

{"animal":{"x":"x"}}

Doch was ich will eigentlich bekommen, ist dies:

{"dog":{"x":"x"}}

Gibt es etwas, was ich so zu AnimalContainer tun kann, dass ich den Laufzeittyp erhalten ( „Hund“, „Katze“) des Objekts, anstelle von „Tiere“)? ( Edit: Ich bin mir bewusst, dass der Name der Map aus dem Getter- und Setter- Methode Namen kommt.) Die einzige Möglichkeit, die ich denken kann, es zu tun innerhalb AnimalContainer ist haben ein Attribut von jeder Art von Tier, haben Setter und Getter für alle von ihnen, und durchzusetzen, daß nur eine zu einer Zeit geschätzt wird. Aber diese Niederlagen der Zweck des Tiersuperklasse mit und scheint einfach falsch. Und in meinem realen Code Ich habe tatsächlich ein Dutzend Unterklassen, nicht nur „Hund“ und „Katze“. Gibt es einen besseren Weg, dies zu tun (vielleicht Anmerkungen irgendwie verwenden)? Ich brauche eine Lösung für Deserialisieren, wie gut.

public class Test
{
   public static void main(String[] args) throws Exception
   {
      AnimalContainer animalContainer = new AnimalContainer();
      animalContainer.setAnimal(new Dog());

      StringWriter sw = new StringWriter();   // serialize
      ObjectMapper mapper = new ObjectMapper(); 
      MappingJsonFactory jsonFactory = new MappingJsonFactory();
      JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
      mapper.writeValue(jsonGenerator, animalContainer);
      sw.close();
      System.out.println(sw.getBuffer().toString());
   }
   public static class AnimalContainer
   {
      private Animal animal;
      public Animal getAnimal() {return animal;}
      public void setAnimal(Animal animal) {this.animal = animal;}
   }
   public abstract static class Animal 
   {
      String x = "x";
      public String getX() {return x;}
   }
   public static class Dog extends Animal {}
   public static class Cat extends Animal {} 
}
War es hilfreich?

Lösung

Wie pro diese announement , Jackson 1.5 Geräte voll polymorpher Typ Handhabung und Rumpf wird nun Code integriert.

Es gibt zwei einfache Möglichkeiten, diese Arbeit zu machen:

  • Fügen Sie @JsonTypeInfo Anmerkung in Supertyp (Tier hier), OR
  • Konfigurieren Objektabbilder von ObjectMapper.enableDefaultTyping () aufrufen (aber wenn ja, muss Tier abstrakten Typ sein)

Andere Tipps

Dies ist wahrscheinlich nicht die Antwort, die Sie suchen, aber es gibt Pläne, die richtige „polymorphe Deserialisierung“ (und notwendige Unterstützung für die Serialisierung für sie) zu implementieren, für Jackson Version 1.4 oder so (also nicht der nächste, 1.3, aber man danach).

Für aktuelle Version, müssen Sie benutzerdefinierte Serializer / Deserializer implementieren: Ich würde wahrscheinlich nur Factory-Methode für die Deserialisierung definieren, und geben Sie Getter für Serializer (definieren ‚getAnimalType‘ oder was auch immer in der abstrakten Basisklasse als abstrakt, Überschreibung in Unterklassen -. oder sogar implementieren nur in der Basisklasse, Leistungsklasse Name der Instanz-Klasse)

Wie auch immer, nur für den Fall wichtig ist es, hier zugrunde liegende Probleme WRT Umsetzung von mit JSON Unterklassen Handhabung und ohne Schemasprache (seit json wirklich hat nicht weit verbreitet eines):

  • , wie Daten (Bean Eigenschaftswerte) von Metadaten (Typinformation nur richtige Subklassen konstruieren erforderlich) trennen - müssen getrennt gehalten werden, aber JSON als Format hat keine Möglichkeit, zu definieren (könnte Konvention zu benennen)
  • , wie richtige Anmerkungen hinzuzufügen solche Metadaten zu erzeugen und zu verwenden; und ohne Abhängigkeit von sprachspezifische Merkmale (sollte nicht zu Java-Klassennamen zum Beispiel binden)

Dies sind lösbare Probleme, aber nicht trivial einfach zu lösen. : -)

Das ist die einzige Art, wie ich mich vorstellen kann, es zu tun, und es ist hässlich. Gibt es einen besseren Weg?

   @JsonWriteNullProperties(false)
   public static class AnimalContainer
   {
      private Animal animal;

      public Animal getCat()
      {
         return animal instanceof Cat ? animal : null;
      }
      public void setCat(Cat cat)
      {
         this.animal = cat;
      }
      public Animal getDog()
      {
         return animal instanceof Dog ? animal : null;
      }
      public void setDog(Dog dog)
      {
         this.animal = dog;
      }
      public Animal getFish()
      {
         return animal instanceof Fish ? animal : null;
      }
      public void setFish(Fish fish)
      {
         this.animal = fish;
      }
   }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top