Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate instances created by InstanceCreator #2446

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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");
}
}