2016-05-24 12 views
1

Ich versuche, eine JSON-Zeichenfolge zu Java-Objekt mit Genson deserialisieren, konnte aber nicht erfolgreich sein. Meine Klassenstruktur ist wie folgt:deserialize JSON zu Java mit polymorphen Mitgliedern

public class Condition { 
} 

public class SimpleCondition extends Condition { 
    String feature; 
    String op; 
    String value; 
    int primitive; 
} 

public class ComplexCondition extends Condition { 
    private Condition left; 
    private String joint; 
    private Condition right; 
} 

Wie Sie sehen können ComplexCondition sowohl für eine weitere ComplexCondition oder ein SimpleCondition als Mitglied haben left und right. Die json, die ich erhalte, ist wie folgt:

{ 
    "left": { 
      "feature":"locality", 
      "op":"==", 
      "value":"Chino" 
      "primitive":9, 
      }, 
    "joint":"and", 
    "right": { 
       "feature":"ch4", 
       "op":">=", 
       "value":"1.5", 
       "primitive":3 
      } 
} 

In diesem json, ein ComplexCondition sowohl left und right als SimpleCondition s hat. Aber eine allgemeine JSON-Zeichenfolge, die ich erhalte, kann von SimpleCondition bis zu einer beliebigen Verschachtelungsebene für ComplexConditions reichen. Ich habe versucht, @class Werte in der JSON-Zeichenfolge, aber immer noch Genson konnte es nicht deserialisieren. Ich freue mich über jede Hilfe bei der Deserialisierung dieses JSON zu Java mit einer beliebigen Bibliothek.

+0

Ich bezweifle, dass JSON von jeder generischen Bibliothek in bereitgestellte Java-Objekte deserialisiert werden kann, da es keine Daten über Java-Klassennamen für die Bibliothek gibt. Wahrscheinlich müssen Sie Ihre eigene Deserialisierung schreiben –

+0

Danke für Ihre Zeit @Lashane. Ich habe die Deserialisierung selbst gemacht, indem ich Konstruktoren in "SimpleCondition" und "ComplexCondition" habe, die ein JSON-Objekt akzeptieren und basierend auf den Objekteigenschaften rekursive Aufrufe in "ComplexCondition" mache. –

Antwort

1

Sie können einige Aliase für Ihre Klassen registrieren und dann, um sie in Ihrem json wie folgt verweisen:

Genson genson = new GensonBuilder() 
    .addAlias("ComplexCondition", ComplexCondition.class) 
    .addAlias("SimpleCondition", SimpleCondition.class) 
    .create(); 

{ 
    "@class": "ComplexCondition", 
    "left": { 
      "@class": "SimpleCondition", 
      "feature":"locality", 
      "op":"==", 
      "value":"Chino", 
      "primitive":9 
      }, 
    "joint":"and", 
    "right": { 
      "@class": "SimpleCondition", 
       "feature":"ch4", 
       "op":">=", 
       "value":"1.5", 
       "primitive":3 
      } 
} 

Sie müssen auch erhalten und Set-Methoden für Ihre ComplexCondition oder machen sein Feld Öffentlichkeit hinzufügen Oder stellen Sie einen Konstruktor bereit, der sie als Argumente akzeptiert, oder konfigurieren Sie geneson so, dass private Felder verwendet werden.

Und letzte Anmerkung, das Metadatenattribut der Klasse muss vor Attributen definiert werden, denen nicht das Präfix @ vorangestellt ist. Wenn Sie dieses Json mit Genson erzeugen, wird es immer diese Einschränkung beachten.

+0

Ich habe das vor dem Stellen der Frage versucht, aber es hat nicht funktioniert. Es initialisiert die 'Condition'-Klasse, setzt aber nichts darauf. Wenn ich also versuche, es auf "Simple" oder "Complex" zu transformieren, bekomme ich eine "ClassCastException". Könnten Sie das bitte einmal überprüfen? –

+0

Wahrscheinlich, weil die Attribute von ComplexCondition alle privat sind und Sie keinen Getter/Setter haben. Ich habe gerade versucht, indem ich get und set-Methoden für sie und alles funktioniert völlig in Ordnung. BTW gibt es einen Tippfehler in der JSON, die es ungültig macht. Ich aktualisierte die Antwort mit dem korrigierten JSON – eugen

+0

Ich habe alle Getter und Setter, ich ignorierte sie einfach in der Frage. Tatsächlich habe ich 'ToString()' Methoden in beiden 'Simple' und' Complex' Zustandsklassen. Das Ergebnis, das ich für dein JSON sehe, ist '([email protected] und [email protected])' wo, was ich erwarte, ist dies - '((locality == Chino) und (ch4> = 1,5)). –

0

Ich kam mit dieser Lösung. Wenn jemand eine bessere Lösung geben kann, würde ich es gerne annehmen.

import org.json.JSONObject; 
public class Condition { 
    public static Condition getCondition(JSONObject json){ 
     if(json.has("left")) 
      return new ComplexCondition(json); 
     else if(json.has("feature")) 
      return new SimpleCondition(json); 
     else 
      throw new IllegalArgumentException("Invalid json for a Condition"); 
    } 
} 

public class ComplexCondition extends Condition{ 
    private Condition left; 
    private String joint; 
    private Condition right; 

    public ComplexCondition(JSONObject json){ 
     if(json.has("left")){ 
      JSONObject leftJSON = json.getJSONObject("left"); 
      if(leftJSON.has("left")) 
       this.left = new ComplexCondition(leftJSON); 
      else 
       this.left = new SimpleCondition(leftJSON); 

      this.joint = json.getString("joint"); 

      JSONObject rightJSON = json.getJSONObject("right"); 
      if(rightJSON.has("left")) 
       this.right = new ComplexCondition(rightJSON); 
      else 
       this.right = new SimpleCondition(rightJSON); 
     } else { 
      throw new IllegalArgumentException("invalid json for a complex condition"); 
     } 
    } 

    //getters and setters 
} 

public class SimpleCondition extends Condition{ 
    private String feature; 
    private String op; 
    private String value; 
    private int primitive; 

    public SimpleCondition(JSONObject json) { 
     if(json.has("feature")){ 
      this.feature = json.getString("feature"); 
      this.op = json.getString("op"); 
      this.value = json.getString("value"); 
      this.primitive = json.getInt("primitive"); 
     } else 
      throw new IllegalArgumentException("invalid json for a simple condition"); 

    } 

    //getters and setters 
}