2016-05-24 5 views
1

Я пытаюсь десериализовать json-строку для java-объекта с помощью genson, но не смог добиться успеха. Моя классовая структура такова:десериализовать Json на Java с членами Polymorphic

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; 
} 

Как вы можете видеть ComplexCondition может иметь другую ComplexCondition или SimpleCondition в качестве своего члена как для left и right. JSON, что я получаю так:

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

В этом формате JSON, ComplexCondition имеет как left и right как SimpleCondition с. Но общая строка json, которую я получаю, может составлять от SimpleCondition до любого уровня вложенности для ComplexCondition s. Я попытался установить значения @class в строке json, но все же genson не смог его десериализовать. Я ценю любую помощь в десериализации этого json для java, используя любую библиотеку.

+0

Я сомневаюсь, что при условии, что json можно десериализовать в предоставленные java-объекты какой-либо общей библиотекой, так как нет данных о именах классов java для использования библиотеки. Вероятно, вам придется написать свою десериализацию –

+0

Спасибо за ваше время @Lashane. Я сделал десериализацию самостоятельно, имея конструкторы как в «SimpleCondition», так и «ComplexCondition», которые принимают объект JSON и на основе свойств объекта в нем. Я делаю рекурсивные вызовы в «ComplexCondition». –

ответ

1

Вы можете зарегистрировать несколько псевдонимов для классов, а затем обращаться к ним в вашем JSON как это:

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 
      } 
} 

Кроме того, необходимо добавить получить и установить методы для ComplexCondition или сделать его поле общественности или предоставить конструктор, который принимает их в качестве аргументов или настраивает genson для использования частных полей.

И последнее примечание: атрибут класса метаданных должен быть определен перед атрибутами, которые не имеют префикса @. Если вы создадите этот json с Genson, он всегда будет уважать это ограничение.

+0

Я пробовал это, прежде чем отправлять вопрос, но это не сработало. Он инициализирует класс 'Condition', но ничего не устанавливает на нем. Поэтому, если я попытаюсь применить его к «Simple» или «Complex», я получу «ClassCastException». Не могли бы вы это проверить? –

+0

Наверное, потому что атрибуты из ComplexCondition являются частными и у вас нет никакого getter/setter. Я просто попытался создать методы get и set для них, и все работает отлично. Кстати, в json есть опечатка, что делает ее недействительной. Я обновил ответ с исправленным json – eugen

+0

У меня есть все получатели и сеттеры, я просто проигнорировал их в вопросе. На самом деле у меня есть методы toString() 'как в классах« Simple », так и« Complex ». Результатом, который я вижу для вашего json, является '([email protected] и [email protected])', где, как я ожидаю, это - '((locality == Chino) и (ch4> = 1,5)). –

0

Я придумал это решение. Если кто-то может дать лучшее решение, я был бы рад принять его.

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 
}