1

I'm using Gson in order to save my classes in a backwards compatible way. I have the following singleton class which I'm trying to serialize.

public class DataHandler implements Serializable {
      private static DataHandler instance; //SINGLETON
      private HashMap<FormIdentification, BaseForm> forms =
        new HashMap<FormIdentification, BaseForm>();

      public void read(){
        //read the json string
        Gson gson = new Gson();
        instance = gson.fromJson(json, DataHandler.class);      
      }

      public void write(){
        Gson gson = new Gson();
        String json = gson.toJson(instance);
        //write the json string
      }
}

public class FormIdentification implements Serializable{
    public String name, type;
    byte[] id;

    public FormIdentification(String name, String type, byte[] id) {
        this.name = name;
        this.type = type;
        this.id = id;
    }
}

public abstract class BaseForm implements Serializable{
    protected FormIdentification identity;
    protected final List<BaseQuestion> questions = new ArrayList<BaseQuestion>();
    protected final HashMap<String, List<String>> personalData = new HashMap<String, List<String>>();
}

public class LinearForm extends BaseForm {
    private DefaultMutableTreeNode criteria;
}

public abstract class BaseQuestion implements Serializable{
    protected String question;
    protected List<String> possibleAnswers;
}

It serializes to the following json:

{
       "forms":{
          "test.Structures.FormIdentification@7b875faa":{
             "criteria":{
                "allowsChildren":true
             },
             "identity":{
                "name":"Mircea",
                "type":"linear",
                "id":[
                   111,
                   119
                ]
             },
             "questions":[

             ],
             "personalData":{
                "Nume":[

                ]
             }
          }
       }
    }

The json is complete and has all the data that the classes contained when it was generated. But when I'm trying to deserialize it gives the following error:

SEVERE: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 12

Note that it was compact formatted, so line 1 column 12 should be: {"forms":{"test.Structures..."

I'm new to json, so I started searching for a solution, but I haven't found one. I tried casting using a TypeToken and I've looked into writing a custom serializer, but haven't managed that. I also tried serializing only the "forms" variables but it gives the same error.

mmimaa
  • 91
  • 9
  • You should put your code in question. Don't post it as links which can die in some time making your question impossible to understand. – Pshemo Jan 25 '14 at 16:48
  • @Pshemo Thank you for your suggestion. I've done as you said. – mmimaa Jan 25 '14 at 16:55

1 Answers1

1

A JSON object is a collection of key/value pairs. The values can be any JSON value: string, number, object, array, true, false, or null. However, the key in a JSON object can only be a string.

When JSON-serializing Map<FormIdentification, BaseForm>, your key is FormIdentification. The best GSON can do is use FormIdentification.toString() to get the string for the key.

However, during JSON-deserialization there is no way to know how to get a FormIdentification from a string.

Glenn Lane
  • 3,892
  • 17
  • 31
  • Thank you for your answer. Now that you said it, when I look at the json it's clear to me why it's not working. I switched to XML using xStream in order to achieve the same thing. – mmimaa Jan 25 '14 at 23:10
  • You could consider a custom JSON serialization, where your map is expressed as a JSON array of objects, where the object has keys `key` and `value` to express each `Map` entry pair: [{"key": {`the serialized key1`}, "value": {`the serialized value1`}}, {"key": {`the serialized key2`}, "value": {`the serialized value2`}}, ...] – Glenn Lane Jan 26 '14 at 21:10