{"record":{"id":"009ac5c7a9171aae","repo":"google/gson","slug":"custom-jsonelement-subclass-classname-is-not-su","errorCode":null,"errorMessage":"Custom JsonElement subclass ${className} is not supported","messagePattern":"Custom JsonElement subclass (.+?) is not supported","errorType":"exception","errorClass":"MalformedJsonException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java","lineNumber":168,"sourceCode":"    } else if (o instanceof JsonArray) {\n      return JsonToken.BEGIN_ARRAY;\n    } else if (o instanceof JsonPrimitive) {\n      JsonPrimitive primitive = (JsonPrimitive) o;\n      if (primitive.isString()) {\n        return JsonToken.STRING;\n      } else if (primitive.isBoolean()) {\n        return JsonToken.BOOLEAN;\n      } else if (primitive.isNumber()) {\n        return JsonToken.NUMBER;\n      } else {\n        throw new AssertionError();\n      }\n    } else if (o instanceof JsonNull) {\n      return JsonToken.NULL;\n    } else if (o == SENTINEL_CLOSED) {\n      throw new IllegalStateException(\"JsonReader is closed\");\n    } else {\n      throw new MalformedJsonException(\n          \"Custom JsonElement subclass \" + o.getClass().getName() + \" is not supported\");\n    }\n  }\n\n  private Object peekStack() {\n    return stack[stackSize - 1];\n  }\n\n  @CanIgnoreReturnValue\n  private Object popStack() {\n    Object result = stack[--stackSize];\n    stack[stackSize] = null;\n    return result;\n  }\n\n  private void expect(JsonToken expected) throws IOException {\n    if (peek() != expected) {\n      throw new IllegalStateException(","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java#L150-L186","documentation":"JsonTreeReader only recognizes JsonObject, JsonArray, JsonPrimitive, and JsonNull on its stack. When peek encounters an object that is none of these (a user-defined JsonElement subclass), it throws MalformedJsonException. This guards the tree-walk against types Gson never produces itself.","triggerScenarios":"Constructing a JsonTreeReader (directly or by passing a JsonElement to Gson) whose root or nested element is an instance of a custom JsonElement subclass that does not extend one of the four standard types.","commonSituations":"Subclassing JsonElement/JsonObject and feeding instances into gson.fromJson(element, type); libraries that introduce proxy JsonElement types.","solutions":["Do not subclass JsonElement; use JsonObject/JsonArray/JsonPrimitive/JsonNull directly.","Convert the custom element to a JsonObject before parsing.","Register a TypeAdapter that handles your custom type instead of relying on tree-reading."],"exampleFix":"// before\nclass MyObj : JsonElement() { ... }\nval reader = JsonTreeReader(MyObj())\nreader.peek() // Custom JsonElement subclass is not supported\n\n// after: use standard JsonObject\nval reader = JsonTreeReader(JsonObject().apply { addProperty(\"k\", 1) })\nreader.peek()","handlingStrategy":"type-guard","validationCode":"// Reject custom JsonElement subclasses before building a tree reader\nstatic boolean isSupportedTreeElement(JsonElement e) {\n  return e == null || e.isJsonNull() || e.isJsonObject() || e.isJsonArray() || e.isJsonPrimitive();\n}\nif (!isSupportedTreeElement(root)) throw new IllegalArgumentException(\"Unsupported element\");\nnew JsonTreeReader(root).peek();","typeGuard":"static boolean isStandardJsonElement(JsonElement e) {\n  return e instanceof JsonObject || e instanceof JsonArray\n      || e instanceof JsonPrimitive || e instanceof JsonNull;\n}","tryCatchPattern":"try {\n  new JsonTreeReader(element).peek();\n} catch (MalformedJsonException e) {\n  if (e.getMessage().startsWith(\"Custom JsonElement subclass\")) {\n    // convert to JsonObject and retry\n    new JsonTreeReader(toJsonObject(element)).peek();\n  } else throw e;\n}","preventionTips":["Never subclass JsonElement; use the four standard subtypes.","Validate element types before constructing a JsonTreeReader.","Register a TypeAdapter for custom element-like types.","Add a guard in test fixtures that builds JsonElement trees."],"tags":["json-tree-reader","custom-subclass","json-element","malformed"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}