Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ static String checkInstantiable(Class<?> c) {
return null;
}

private static <T> T useInstanceCreator(InstanceCreator<T> instanceCreator, Type type, Class<?> rawType) {
T instance = instanceCreator.createInstance(type);
if (instance == null) {
throw new RuntimeException("InstanceCreator " + instanceCreator + " returned null for type " + type);
}

if (!rawType.isInstance(instance)) {
throw new ClassCastException("InstanceCreator " + instanceCreator + " created instance of wrong type;"
+ " expected " + rawType.getName() + " but got instance of unrelated type " + instance.getClass().getName());
}
return instance;
}

public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
final Type type = typeToken.getType();
final Class<? super T> rawType = typeToken.getRawType();
Expand All @@ -100,7 +113,7 @@ public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
if (typeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return typeCreator.createInstance(type);
return useInstanceCreator(typeCreator, type, rawType);
}
};
}
Expand All @@ -112,7 +125,7 @@ public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return rawTypeCreator.createInstance(type);
return useInstanceCreator(rawTypeCreator, type, rawType);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.gson.functional;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
Expand All @@ -33,7 +34,7 @@
import org.junit.Test;

/**
* Functional Test exercising custom serialization only. When test applies to both
* Functional Test exercising custom deserialization only. When test applies to both
* serialization and deserialization then add it to CustomTypeAdapterTest.
*
* @author Inderjeet Singh
Expand Down Expand Up @@ -129,4 +130,48 @@ class SubTreeSet<T> extends TreeSet<T> {}
assertThat(set.first()).isEqualTo("b");
assertThat(set.getClass()).isEqualTo(SubTreeSet.class);
}

private static class CustomClass {}

@Test
public void testInstanceCreatorReturnsNull() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(CustomClass.class, new InstanceCreator<CustomClass>() {
@Override
public CustomClass createInstance(Type type) {
return null;
}

@Override
public String toString() {
return "bad-instance-creator";
}
})
.create();

RuntimeException e = assertThrows(RuntimeException.class, () -> gson.fromJson("{}", CustomClass.class));
assertThat(e).hasMessageThat().isEqualTo("InstanceCreator bad-instance-creator returned null for"
+ " type class " + CustomClass.class.getName());
}

@Test
public void testInstanceCreatorReturnsWrongInstance() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(CustomClass.class, new InstanceCreator<String>() {
@Override
public String createInstance(Type type) {
return "test";
}

@Override
public String toString() {
return "bad-instance-creator";
}
})
.create();

ClassCastException e = assertThrows(ClassCastException.class, () -> gson.fromJson("{}", CustomClass.class));
assertThat(e).hasMessageThat().isEqualTo("InstanceCreator bad-instance-creator created instance of wrong type;"
+ " expected " + CustomClass.class.getName() + " but got instance of unrelated type java.lang.String");
}
}