apache/dolphinscheduler · error · RuntimeException
Json deserialization exception.
Error message
Json deserialization exception.
What it means
JSONUtils.parseArray(String) parses a JSON string into an ArrayNode by delegating to objectMapper.readTree and casting. Any parsing failure is wrapped in a RuntimeException with this message. It fails both when the text is invalid JSON and when the parsed tree is not an array (ClassCastException from the cast).
Source
Thrown at dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/JSONUtils.java:353
}
public static ObjectNode parseObject(String text) {
try {
if (StringUtils.isEmpty(text)) {
return parseObject(text, ObjectNode.class);
} else {
return (ObjectNode) objectMapper.readTree(text);
}
} catch (Exception e) {
throw new RuntimeException("String json deserialization exception.", e);
}
}
public static ArrayNode parseArray(String text) {
try {
return (ArrayNode) objectMapper.readTree(text);
} catch (Exception e) {
throw new RuntimeException("Json deserialization exception.", e);
}
}
/**
* json serializer
*/
public static class JsonDataSerializer extends JsonSerializer<String> {
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeRawValue(value);
}
}
public static class JsonDataDeserializer extends JsonDeserializer<String> {
@OverrideView on GitHub (pinned to 02eac45a1b)
Solutions
- Check the input string: it must start with '[' and be well-formed JSON
- Verify the upstream schema — if the value may be an object, parse with parseObject and read the array field from it
- Catch the RuntimeException and return Collections.emptyList() when the input is optional/blank
- Validate the payload shape with readTree + isArray before casting
- Fix the producer so it emits a JSON array
Example fix
// before
ArrayNode nodes = JSONUtils.parseArray(configJson);
// after
ArrayNode nodes = configJson != null && configJson.trim().startsWith("[")
? JSONUtils.parseArray(configJson)
: JsonNodeFactory.instance.arrayNode(); Defensive patterns
Strategy: validation
Validate before calling
boolean isValidJsonArray(String s) {
if (s == null || !s.trim().startsWith("[")) return false;
try { return JSONUtils.parseArray(s).isArray(); } catch (Exception e) { return false; }
} Type guard
ArrayNode safeParseArray(String s) {
if (s == null || !s.trim().startsWith("[")) return JsonNodeFactory.instance.arrayNode();
try { return JSONUtils.parseArray(s); } catch (Exception e) { return JsonNodeFactory.instance.arrayNode(); }
} Try / catch
try {
ArrayNode arr = JSONUtils.parseArray(text);
} catch (RuntimeException e) {
log.warn("Expected a JSON array but got: {}", text, e);
arr = JsonNodeFactory.instance.arrayNode();
} Prevention
- Confirm the payload shape (array vs object) against the producer's schema
- Guard with a startsWith("[") check when the shape is not guaranteed
- Handle schema drift between service versions explicitly
- Return empty collections instead of crashing when the field is optional
When it happens
Trigger: Calling JSONUtils.parseArray(text) where text is malformed JSON, or where text is valid JSON but not an array (e.g. an object '{...}', a bare string, or a number), causing readTree to succeed but the (ArrayNode) cast to fail.
Common situations: An API or config value that changed shape across versions from array to object; passing a JSON object where a list was expected; empty or whitespace-only string produced by a failed upstream call.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- String json deserialization exception.
- Parse json: <json> to class: <clazz> failed
- ${e.getMessage()}
- 10140
- Parse json: <json> to list of class: <clazz> failed
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/fd7c8a86ef42a52c.
Report an issue: GitHub.