{"record":{"id":"1db3c809353d2a36","repo":"google/gson","slug":"attempted-to-deserialize-a-java-lang-class-forgot","errorCode":null,"errorMessage":"Attempted to deserialize a java.lang.Class. Forgot to register a type adapter?\nSee ${url}","messagePattern":"Attempted to deserialize a java\\.lang\\.Class\\. Forgot to register a type adapter\\?\nSee (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java","lineNumber":83,"sourceCode":"    throw new UnsupportedOperationException();\n  }\n\n  @SuppressWarnings(\"rawtypes\")\n  public static final TypeAdapter<Class> CLASS =\n      new TypeAdapter<Class>() {\n        @Override\n        public void write(JsonWriter out, Class value) throws IOException {\n          throw new UnsupportedOperationException(\n              \"Attempted to serialize java.lang.Class: \"\n                  + value.getName()\n                  + \". Forgot to register a type adapter?\"\n                  + \"\\nSee \"\n                  + TroubleshootingGuide.createUrl(\"java-lang-class-unsupported\"));\n        }\n\n        @Override\n        public Class read(JsonReader in) throws IOException {\n          throw new UnsupportedOperationException(\n              \"Attempted to deserialize a java.lang.Class. Forgot to register a type adapter?\"\n                  + \"\\nSee \"\n                  + TroubleshootingGuide.createUrl(\"java-lang-class-unsupported\"));\n        }\n      }.nullSafe();\n\n  public static final TypeAdapterFactory CLASS_FACTORY = newFactory(Class.class, CLASS);\n\n  public static final TypeAdapter<BitSet> BIT_SET =\n      new TypeAdapter<BitSet>() {\n        @Override\n        public BitSet read(JsonReader in) throws IOException {\n          BitSet bitset = new BitSet();\n          in.beginArray();\n          int i = 0;\n          JsonToken tokenType = in.peek();\n          while (tokenType != JsonToken.END_ARRAY) {\n            boolean set;","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java#L65-L101","documentation":"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.","triggerScenarios":"Deserializing JSON into an object that has a field of type Class<?> via gson.fromJson() without registering a custom TypeAdapter for Class.","commonSituations":"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.","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"],"exampleFix":"// before\nclass Entity {\n    String name;\n    Class<?> type; // causes UnsupportedOperationException on deserialize\n}\ngson.fromJson(\"{\\\"type\\\":\\\"com.example.Foo\\\"}\", Entity.class);\n\n// after\nGson gson = new GsonBuilder()\n    .registerTypeAdapter(Class.class, (JsonDeserializer<Class<?>>) (j, t, c) ->\n        Class.forName(j.getAsString()))\n    .create();","handlingStrategy":"validation","validationCode":"// Check model classes for Class fields before deserializing\npublic static boolean hasClassField(Class<?> type) {\n    for (Field f : type.getDeclaredFields()) {\n        if (f.getType() == Class.class && !Modifier.isTransient(f.getModifiers())) {\n            return true; // will trigger UnsupportedOperationException on deserialize\n        }\n    }\n    return false;\n}","typeGuard":null,"tryCatchPattern":"try {\n    Entity e = gson.fromJson(json, Entity.class);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"Attempted to deserialize a java.lang.Class\")) {\n        // register a TypeAdapter<Class<?>> or change the field type to String\n    }\n}","preventionTips":["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"],"tags":["deserialization","class","type-adapter","security"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}