Skip to content

Instantly share code, notes, and snippets.

@chriscasola
Created January 23, 2013 03:27
Show Gist options
  • Save chriscasola/4601642 to your computer and use it in GitHub Desktop.
Save chriscasola/4601642 to your computer and use it in GitHub Desktop.
This snippet shows how to write a custom deserializer for Gson that can handle a class with a generic type parameter. In this case, the DefectChangeset class is being deserialized, which has a field called changes of type Map<String, FieldChange<?>>. There may be better ways to do this, but it works.
public class DefectChangeset extends DefectEvent {
private Map<String, FieldChange<?>> changes;
/**
* Construct a DefectChangeset with default properties.
*/
public DefectChangeset() {
type = EventType.CHANGESET;
changes = new HashMap<String, FieldChange<?>>();
}
...
public class DefectChangesetDeserializer implements JsonDeserializer<DefectChangeset> {
@Override
public DefectChangeset deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
// hash map to hold the deserialized FieldChange objects
HashMap<String, FieldChange<?>> changesMap = new HashMap<String, FieldChange<?>>();
JsonObject changeSet = json.getAsJsonObject();
if (changeSet.has("changes")) {
JsonObject changes = changeSet.get("changes").getAsJsonObject();
if (changes.has("title")) {
JsonObject titleObj = changes.get("title").getAsJsonObject();
String oldTitle = context.deserialize(titleObj.get("oldValue"), String.class);
String newTitle = context.deserialize(titleObj.get("newValue"), String.class);
changesMap.put("title", new FieldChange<String>(oldTitle, newTitle));
}
if (changes.has("description")) {
JsonObject descriptionObj = changes.get("description").getAsJsonObject();
String oldDesc = context.deserialize(descriptionObj.get("oldValue"), String.class);
String newDesc = context.deserialize(descriptionObj.get("newValue"), String.class);
changesMap.put("description", new FieldChange<String>(oldDesc, newDesc));
}
if (changes.has("assignee")) {
JsonObject assigneeObj = changes.get("assignee").getAsJsonObject();
User oldUser = context.deserialize(assigneeObj.get("oldValue"), User.class);
User newUser = context.deserialize(assigneeObj.get("newValue"), User.class);
changesMap.put("assignee", new FieldChange<User>(oldUser, newUser));
}
if (changes.has("tags")) {
JsonObject tagsObj = changes.get("tags").getAsJsonObject();
Tag[] oldTags = context.deserialize(tagsObj.get("oldValue"), Tag[].class);
Tag[] newTags = context.deserialize(tagsObj.get("newValue"), Tag[].class);
changesMap.put("tags", new FieldChange<Set<Tag>>(new HashSet<Tag>(new ArrayList<Tag>(Arrays.asList(oldTags))), new HashSet<Tag>(new ArrayList<Tag>(Arrays.asList(newTags)))));
}
if (changes.has("status")) {
JsonObject statusObj = changes.get("status").getAsJsonObject();
DefectStatus oldStatus = context.deserialize(statusObj.get("oldValue"), DefectStatus.class);
DefectStatus newStatus = context.deserialize(statusObj.get("newValue"), DefectStatus.class);
changesMap.put("status", new FieldChange<DefectStatus>(oldStatus, newStatus));
}
// reconstruct the DefectChangeset
DefectChangeset retVal = new DefectChangeset();
retVal.setChanges(changesMap);
retVal.setDate((Date)(context.deserialize(changeSet.get("date"), Date.class)));
retVal.setUser((User)(context.deserialize(changeSet.get("user"), User.class)));
// return the DefectChangeset
return retVal;
}
else {
throw new JsonParseException("DefectChangeset type is unrecognized");
}
}
}
/**
* Persistent Model that holds and old and new value for some field.
*
* @param <T> the type of the field that was changed
*/
public class FieldChange<T> implements Model {
private final T oldValue;
private final T newValue;
/**
* @param oldValue the old value of a field before it was changed
* @param newValue the new value of a field after it was changed
*/
public FieldChange(T oldValue, T newValue) {
this.oldValue = oldValue;
this.newValue = newValue;
}
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment