samedi 27 juin 2015

Gson parse a Json object with generic type

I have the following json written into a file which i want to read via Gson:

{
  "identifier": "CONFIG",
  "data": [
    {
      "identifier": "HOTKEY",
      "data": {
        "hotKey": "testKey1",
        "type": "APPLICATION",
        "runnableContext": "testContext1"
      }
    },
    {
      "identifier": "HOTKEY",
      "data": {
        "hotKey": "testKey2",
        "type": "APPLICATION",
        "runnableContext": "testContext2"
      }
    }
  ]
}

In the above Json, you can see that the Identifier & data construct is recursively repeated. So the basic class representing this repeated pattern is a generic one as shown below:

{
  "identifier": "CONFIG",
  "data": {

  }
}

This pattern is represented by the JsonData class as follows:

import java.util.Set;

import com.cerner.system.exception.Verifier;
import com.cerner.system.exception.VerifyException;
import com.google.common.collect.ImmutableSet;

/**
 * Class representing a simple {@link JsonData#identifier}, 
 * {@link JsonData#data}  format. This class can be used to 
 * persist application data for example in a Configuration file.
 * 
 * @author SW029693
 * @since v1.0
 */
public class JsonData <T>{
    /**
     * Represents a unique identifier 
     */
    private String identifier;
    /**
     * Represents the data pertaining to this {@link JsonData#identifier} 
     */
    private T data;

    private static final Set<String> VALID_JSON_ID_TYPES = ImmutableSet.of("CONFIG","HOTKEYS","HOTKEY","RECOMMENDATIONS");

    public JsonData(String identifier, T data) {
        super();
        this.identifier = identifier;
        this.data = data;
    }

    /**
     * Getter for {@link JsonData#identifier} 
     * @return
     */
    public String getIdentifier() {
        return identifier;
    }

    /**
     * Sets the {@link JsonData#identifier} to the given value
     * @param  identifier
     *         Represents a unique {@link JsonData#identifier}  
     * @throws VerifyException
     *         If the argument is {@code null} or {@code empty}
     */
    public void setIdentifier(String identifier) throws VerifyException{
        Verifier.verifyNotNull(identifier, "identifier : null");
        Verifier.verifyNotEmpty(identifier,"identifier : empty");
        this.identifier = identifier;
    }

    /**
     * Getter for {@link JsonData} 
     * @return
     */
    public T getData() {
        return data;
    }

    /**
     * Sets the {@link JsonData#data} to the given value
     * @param  identifier
     *         Represents a unique {@link JsonData#data}  
     * @throws VerifyException
     *         If the argument is {@code null} 
     */
    public void setData(T data) {
        Verifier.verifyNotNull(data, "data : null");
        this.data = data;
    }

    @Override
    public String toString() {
        return "JsonData [identifier=" + identifier + ", data=" + data + "]";
    }
}

Also, in the Json above, you can see that the data inside each hotkey. This data is to be held in a ConfigurationProperty class after reading the json via gson:

public class ConfigurationProperty implements Comparable<ConfigurationProperty>, Serializable{
....    
private final String hotKey;
private final String type;
private final String runnableContext;
....

Now the question. I am trying to read the file and parse the Json to store it into respective objects using GSON with no luck.

I have some working code to read a single JsonData object written to the file:

    {
      "identifier": "HOTKEY",
      "data": {
        "hotKey": "testKey1",
        "type": "APPLICATION",
        "runnableContext": "testContext1"
      }
    }

is succesfully read by:

private static JsonData<ConfigurationProperty> readconfigFile() {
    Reader reader = null;
    JsonData<ConfigurationProperty> data = null;
    Gson gson  = null;
    Type confType;
    try {
        reader = new FileReader("./config.json");
        gson = new GsonBuilder().create();
        confType = new TypeToken<JsonData<ConfigurationProperty>>() {}.getType();

        data = gson.fromJson(reader,confType);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        fail("Test failed while reading the config.json file: "+e.getMessage());        }
    finally {
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
            fail("Test failed while reading the config.json file: "+e.getMessage());
        }
    }
    return data;
}

But if you look at the first json, this is now a recursive structure of JsonData. Also while parsing, i need to tell Gson that the first data object is an ARRAY of JsonData objects. And I also need to tell gson that each JSONData object in that array is of type ConfigurationProperty.

I am not sure how to do this.

Please help!

Thanks

Aucun commentaire:

Enregistrer un commentaire