Created
January 23, 2013 03:27
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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<?>>(); | |
} | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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