karatelabs/karate · error · RuntimeException
Failed to deserialize JSON to
Error message
Failed to deserialize JSON to ${className}: ${e.getMessage()} What it means
Json.fromJson(json, className) loads the named class via Class.forName and asks JSONValue to parse the JSON string directly into an instance of that class. If the class cannot be loaded, the JSON is malformed, or the JSON shape does not map to the class, the original exception is caught and rethrown as a RuntimeException with the class name and underlying message.
Solutions
- Validate the json string parses (e.g. JSONValue.parse(json)) before deserializing to the typed class.
- Verify className is the exact fully-qualified name of a class available on the runtime classpath.
- Check the wrapped exception (getCause()) to distinguish ClassNotFoundException from parse/type-mapping failures.
- Ensure the target class has a compatible structure (public fields/setters/constructor) for the JSON being parsed.
Example fix
// before
Object o = Json.fromJson(body, "com.example.MissingDto");
// after
String cls = "com.example.MyDto"; // verify class exists and is on classpath
try {
Object probe = JSONValue.parse(body); // syntax check first
} catch (Exception e) {
throw new IllegalStateException("body is not valid JSON", e);
}
Object o = Json.fromJson(body, cls); Defensive patterns
Strategy: validation
Validate before calling
// before calling Json.fromJson
if (json == null || json.isBlank()) throw new IllegalArgumentException("empty json");
JSONValue.parse(json); // throws early if not valid JSON
Class.forName(className); // throws early if class missing Try / catch
try {
Object o = Json.fromJson(json, className);
} catch (RuntimeException e) {
Throwable cause = e.getCause();
// branch on ClassNotFoundException vs parse/mapping failure
} Prevention
- Keep target DTO classes stable and on the compile+runtime classpath.
- Parse generically first to sanity-check payloads before typed deserialization.
- Store fully-qualified class names as constants, not inline strings.
When it happens
Trigger: Calling Json.fromJson(String json, String className) where: className is misspelled or not on the classpath (Class.forName fails); the json string is invalid JSON; the JSON structure does not fit the target class's fields/constructor.
Common situations: Typo in a fully-qualified class name; target class moved/renamed between library versions; parsing a response body whose shape changed; passing non-JSON text (e.g. HTML error page) as the json argument.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- invalid json: input is null or blank
- invalid json: not a JSON object or array
- invalid json
- boot.ext(' '): failed to construct
- remove() needs two arguments: variable name and path
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/b75ec6f480477a59.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/common/Json.java:591
}
for (Object v : arr) {
if (hasCycle(v, seen)) return true;
}
seen.remove(o);
}
return false;
}
/**
* Deserialize a JSON string into a Java object of the specified class.
* Uses json-smart's JSONValue.parse for bean mapping.
*/
public static Object fromJson(String json, String className) {
try {
Class<?> clazz = Class.forName(className);
return JSONValue.parse(json, clazz);
} catch (Exception e) {
throw new RuntimeException("Failed to deserialize JSON to " + className + ": " + e.getMessage(), e);
}
}
}
View on GitHub (pinned to a22eb90246)