Skip to content

Instantly share code, notes, and snippets.

@wischweh
Last active October 31, 2015 05:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wischweh/c55265d0883c4e4ab350 to your computer and use it in GitHub Desktop.
Save wischweh/c55265d0883c4e4ab350 to your computer and use it in GitHub Desktop.
package com.twobox.evaluategson_jsonapi.deserialize;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
/**
* This is a implementation to unflatten JSON which is structured according to http://jsonapi.org/ specification (and hence is flat)
* and make it mappable to regular POJOs.
*
* The idea is based on http://stackoverflow.com/questions/11271375/gson-custom-seralizer-for-one-variable-of-many-in-an-object-using-typeadapter
*
* Created by wischweh1 on 02.07.15.
*/
public class JSONApiTypeAdapterFactory<C>
implements TypeAdapterFactory {
private final Class<C> customizedClass;
public static final String JSONAPI_KEYWORD_ID="id";
public static final String JSONAPI_KEYWORD_TYPE="type";
public static final String JSONAPI_KEYWORD_ATTRIBUTES="attributes";
public JSONApiTypeAdapterFactory(Class<C> customizedClass) {
this.customizedClass = customizedClass;
}
@SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == customizedClass
? (TypeAdapter<T>) customizeMyClassAdapter(gson, (TypeToken<C>) type)
: null;
}
private TypeAdapter<C> customizeMyClassAdapter(Gson gson, TypeToken<C> type) {
final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<C>() {
@Override public void write(JsonWriter out, C value) throws IOException {
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}
@Override public C read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
JsonElement unflattenedTree=unflatten(tree);
return delegate.fromJsonTree(unflattenedTree);
}
};
}
/**
* Override this to muck with {@code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(C source, JsonElement toSerialize) {
// TODO: Implement this
}
/**
* Override this to muck with {@code deserialized} before it parsed into
* the application type.
*/
protected JsonElement unflatten(JsonElement deserialized) {
JsonObject result=new JsonObject();
JsonObject dataNode=deserialized.getAsJsonObject();
result.add(JSONAPI_KEYWORD_ID, dataNode.get(JSONAPI_KEYWORD_ID));
JsonObject attributes=dataNode.getAsJsonObject(JSONAPI_KEYWORD_ATTRIBUTES);
for (Map.Entry<String, JsonElement> entry : attributes.entrySet()) {
result.add(entry.getKey(),entry.getValue());
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment