vendredi 3 novembre 2017

Javafx - Converting a json file to an interface java object

I have a structure where there is a group which may contain leaf items or other groups too, so I implemented the Composite design pattern using a "SavedItem" interface with 2 subclasses "Rectangle" which represents the leaf node and "Group" where Group contains an arraylist of SavedItem objects to implement this composition hierarchy. I used Gson to export the structure I have as a json file. The exported object is basically an arraylist of SavedItem objects and everything worked fine. However, the application requires loading a json file as well and converting it back to java objects, so I also used Gson but as I am trying to retrieve an arraylist of the interface "SavedItem" I am getting this exception:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: Unable to invoke no-args constructor for interface SavedItem. Register an InstanceCreator with Gson for this type may fix this problem.

This is the "SavedItem" interface:

public interface SavedItem {

    public String getId();
    public String getDescription();
    public Boolean getIsGroup();
    public void addSavedItem(SavedItem savedItem);

}

This is the leaf node class "Rectangle" (of course with all setters and getters):

public class Rectangle implements SavedItem{

private String id;
private String type;
private String description;
private  Point startingPoint ;
private  double width;
private double height;
private boolean isGroup;

public Rectangle(){}

public Rectangle(Point startingPoint, double width, double height, String type , String description) {
    this.id = "FIELD-" + UUID.randomUUID().toString();
    this.startingPoint = startingPoint;
    this.width = width;
    this.height = height;
    this.type= type;
    this.description = description;
    this.isGroup = false;
}

And this is the Group class (in addition to setters and getters):

public class Group implements SavedItem{


private String id;
private String description;
ArrayList<SavedItem> groupFields = new ArrayList<SavedItem>();
private boolean isGroup;

public Group(){}

public Group(String description) {
    this.id = "GROUP-" + UUID.randomUUID().toString();
    this.description = description;
    this.isGroup = true;
}

The main object (called MedicalForm) contains this arraylist:

private ArrayList<SavedItem> StructuredFields = new ArrayList<>();

Creating the json file is done like this:

   try {
        Writer writer = new FileWriter(path+"/"+ form.getFormName()+".json");
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        JsonObject object = new JsonObject();
        object.addProperty("id", form.getId());
        object.addProperty("formName", form.getFormName());
        JsonElement element = gson.toJsonTree(form.getStructuredFields());
        object.add("StructuredFields", element);
        object.addProperty("imageString", form.getImageString());
        gson.toJson(object,writer);
        writer.close();
    } catch (IOException e) {

        e.printStackTrace();
    }

And loading a json and converting it back to java objects is done like this:

JsonReader reader = new JsonReader(new FileReader(path));    
Gson gson = new Gson();
MedicalForm response = gson.fromJson(reader, MedicalForm.class);
form.setId(response.getId());
form.setFormName(response.getFormName());
form.setStructuredFields(response.getStructuredFields()); 
form.setImageString(response.getImageString());

I searched for the problem and I found solutions saying I should add a default constructor and so I did in both Group and Rectangle classes in addition to the class where I am trying to convert json to java object. However, I can't add a constructor in the interface, and replacing the interface with a superclass will prevent the flexibility of casting. How can I solve this issue and convert the json properly to java objects?

Aucun commentaire:

Enregistrer un commentaire