@Override
  public GenericType deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
    JsonObject root = (JsonObject) json;

    ImmutableGenericType.Builder builder = ImmutableGenericType.builder();

    JsonElement value = root.get(VALUE_PROPERTY);
    if (value == null) {
      throw new JsonParseException(String.format("%s not found for %s in JSON", VALUE_PROPERTY, type));
    }

    if (value.isJsonObject()) {
      final String valueTypeName = value.getAsJsonObject().get(GenericType.TYPE_PROPERTY).getAsString();
      try {
        Class<?> valueType = Class.forName(valueTypeName);
        builder.value(context.deserialize(value, valueType));
      } catch (ClassNotFoundException e) {
        throw new JsonParseException(String.format("Couldn't construct value class %s for %s", valueTypeName, type), e);
      }
    } else if (value.isJsonPrimitive()) {
      final JsonPrimitive primitive = value.getAsJsonPrimitive();
      if (primitive.isString()) {
        builder.value(primitive.getAsString());
      } else if (primitive.isNumber()) {
        builder.value(primitive.getAsInt());
      } else if (primitive.isBoolean()) {
        builder.value(primitive.getAsBoolean());
      }
    } else {
      throw new JsonParseException(
          String.format("Couldn't deserialize %s : %s. Not a primitive or object", VALUE_PROPERTY, value));
    }

    return builder.build();

  }
Custom serializer which allows to (JSON) store different types of objects inside same class :
{@link GenericType}
mongo/test/org/immutables/mongo/fixture/generic/GenericTypeJsonSerializer.java