Gson custom serialization

gson, java, json, serialization

Solution

Looking at the source for Gson, I have found what I think is the issue:

// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);

// user's type adapters
factories.addAll(typeAdapterFactories);

As you can see the `ObjectTypeAdapter` will take precedence over my factory.

The only solution as far as I can see is to use reflection to remove the `ObjectTypeAdapter` from the list or insert my factory before it. I have done this and it works.

Problem

I wish to have a custom GSON deserializer such that whenever it is deserializing a JSON object (i.e. anything within curly brackets `{ ... }`), it will look for a `$type` node and deserialize using its inbuilt deserializing capability to that type. If no `$type` object is found, it just does what it normal does. So for example, I would want this to work: ``` { "$type": "my.package.CustomMessage" "payload" : { "$type": "my.package.PayloadMessage", "key": "value" } } public class CustomMessage { public Object payload; } public class PayloadMessage implements Payload { public String key; } ``` Calling: `Object customMessage = gson.fromJson(jsonString, Object.class)`. So currently if I change the `payload` type to the `Payload` interface: ``` public class CustomMessage { public Payload payload; } ``` Then the following `TypeAdapaterFactory` will do what I want: ``` final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class); final PojoTypeAdapter thisAdapter = this; public T read(JsonReader reader) throws IOException { JsonElement jsonElement = (JsonElement)elementAdapter.read(reader); if (!jsonElement.isJsonObject()) { return delegate.fromJsonTree(jsonElement); } JsonObject jsonObject = jsonElement.getAsJsonObject(); JsonElement typeElement = jsonObject.get("$type"); if (typeElement == null) { return delegate.fromJsonTree(jsonElement); } try { return (T) gson.getDelegateAdapter( thisAdapter, TypeToken.get(Class.forName(typeElement.getAsString()))).fromJsonTree(jsonElement); } catch (ClassNotFoundException ex) { throw new IOException(ex.getMessage()); } } ``` However, I would like it to work when `payload` is of type `Object` or any type for that matter, and throw some sort of type match exception if it can't assign the variable.

Original source