google/gson · error · UnsupportedOperationException
Attempted to deserialize a java.lang.Class. Forgot to…
Error message
Attempted to deserialize a java.lang.Class. Forgot to register a type adapter?
See ${url} What it means
Gson's built-in CLASS adapter throws UnsupportedOperationException on read because deserializing an arbitrary java.lang.Class from JSON is a security risk (class loading). The adapter fires whenever Gson encounters a Class field during deserialization and no custom adapter was registered.
Solutions
- Register a custom JsonDeserializer<Class<?>> that maps a class-name string to Class.forName with an allowlist
- Replace the Class<?> field with a String type identifier and resolve the class separately
- Mark the field with @Expose(deserialize = false) so Gson ignores it during deserialization
Example fix
// before
class Entity {
String name;
Class<?> type; // causes UnsupportedOperationException on deserialize
}
gson.fromJson("{\"type\":\"com.example.Foo\"}", Entity.class);
// after
Gson gson = new GsonBuilder()
.registerTypeAdapter(Class.class, (JsonDeserializer<Class<?>>) (j, t, c) ->
Class.forName(j.getAsString()))
.create(); Defensive patterns
Strategy: validation
Validate before calling
// Check model classes for Class fields before deserializing
public static boolean hasClassField(Class<?> type) {
for (Field f : type.getDeclaredFields()) {
if (f.getType() == Class.class && !Modifier.isTransient(f.getModifiers())) {
return true; // will trigger UnsupportedOperationException on deserialize
}
}
return false;
} Try / catch
try {
Entity e = gson.fromJson(json, Entity.class);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("Attempted to deserialize a java.lang.Class")) {
// register a TypeAdapter<Class<?>> or change the field type to String
}
} Prevention
- Replace Class<?> fields with String type identifiers and resolve them with an allowlist
- Register a custom JsonDeserializer<Class<?>> that validates class names against an allowlist
- Mark Class fields with @Expose(deserialize = false) if they are set programmatically
When it happens
Trigger: Deserializing JSON into an object that has a field of type Class<?> via gson.fromJson() without registering a custom TypeAdapter for Class.
Common situations: A DTO with a Class<?> field receives JSON input; polymorphic type handling that naively uses Class fields; legacy models migrated from a framework that supported class deserialization.
Related errors
- Attempted to serialize java.lang.Class
- cannot deserialize subtype named ; did you forget to…
- Adapter for type with cyclic dependency has been used…
- Array must have size 1, but has size
- Cannot allocate . Usage of JDK sun.misc.Unsafe is enabled…
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/1db3c809353d2a36.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java:83
throw new UnsupportedOperationException();
}
@SuppressWarnings("rawtypes")
public static final TypeAdapter<Class> CLASS =
new TypeAdapter<Class>() {
@Override
public void write(JsonWriter out, Class value) throws IOException {
throw new UnsupportedOperationException(
"Attempted to serialize java.lang.Class: "
+ value.getName()
+ ". Forgot to register a type adapter?"
+ "\nSee "
+ TroubleshootingGuide.createUrl("java-lang-class-unsupported"));
}
@Override
public Class read(JsonReader in) throws IOException {
throw new UnsupportedOperationException(
"Attempted to deserialize a java.lang.Class. Forgot to register a type adapter?"
+ "\nSee "
+ TroubleshootingGuide.createUrl("java-lang-class-unsupported"));
}
}.nullSafe();
public static final TypeAdapterFactory CLASS_FACTORY = newFactory(Class.class, CLASS);
public static final TypeAdapter<BitSet> BIT_SET =
new TypeAdapter<BitSet>() {
@Override
public BitSet read(JsonReader in) throws IOException {
BitSet bitset = new BitSet();
in.beginArray();
int i = 0;
JsonToken tokenType = in.peek();
while (tokenType != JsonToken.END_ARRAY) {
boolean set;View on GitHub (pinned to 310ac341f2)