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 implements TypeAdapterFactory { private final Class 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 customizedClass) { this.customizedClass = customizedClass; } @SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal public final TypeAdapter create(Gson gson, TypeToken type) { return type.getRawType() == customizedClass ? (TypeAdapter) customizeMyClassAdapter(gson, (TypeToken) type) : null; } private TypeAdapter customizeMyClassAdapter(Gson gson, TypeToken type) { final TypeAdapter delegate = gson.getDelegateAdapter(this, type); final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); return new TypeAdapter() { @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 entry : attributes.entrySet()) { result.add(entry.getKey(),entry.getValue()); } return result; } }