stanfordnlp/CoreNLP · error · RuntimeException
Unknown object to serialize
Error message
Unknown object to serialize: ${value} What it means
routeObject is JSONOutputter's type-dispatch: it walks through known Java types (String, Number, Boolean, Iterable, Map, arrays, etc.) and serializes each. If the value's class matches none of the branches — even after primitive boxing — a RuntimeException 'Unknown object to serialize' is thrown.
Solutions
- Convert the value to a JSON-friendly type (String, Number, Boolean, List, Map) before writing output
- Implement a custom JSONOutputter/Outputter that knows how to serialize your object type
- Remove or filter non-serializable annotation keys before calling JSONOutputter.write
- Prefer Objects.toString(value) if a plain string representation is acceptable
Example fix
// before
map.put("timestamp", new Date()); // RuntimeException
// after
map.put("timestamp", new Date().toInstant().toString()); Defensive patterns
Strategy: validation
Validate before calling
for (Object v : values) {
if (!(v instanceof String || v instanceof Number || v instanceof Boolean
|| v instanceof Iterable || v instanceof Map
|| (v != null && v.getClass().isArray())))
throw new IllegalArgumentException("Not JSON-serializable: " + v.getClass());
} Type guard
static boolean isJsonSerializable(Object v) {
return v == null || v instanceof String || v instanceof Number || v instanceof Boolean
|| v instanceof Iterable || v instanceof Map || v.getClass().isArray();
} Try / catch
try {
JSONOutputter.jsonPrint(writer, ann);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Unknown object to serialize")) {
// strip/convert custom keys and retry
} else throw e;
} Prevention
- Convert custom objects to Strings/primitives/Maps before annotation output
- Filter out non-serializable custom annotation keys before JSON dumping
- Round-trip test JSON output whenever adding new annotator keys
- Use Objects.toString() for opaque objects if a string form suffices
When it happens
Trigger: Placing an arbitrary object (custom class, URI, Date, CoreLabel, etc.) into an annotation value or map that JSONOutputter attempts to render; the object is not a String, Number, Boolean, Collection, Map, or array.
Common situations: Custom annotators storing rich Java objects under custom keys and then expecting JSONOutputter to dump the whole annotation; forgetting to convert objects like Date or custom feature structures to primitives/strings first.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unhandled primitive type in array
- RuntimeIOException wrapping IOException
- Failed to save classifier
- ERROR: Invalid dependency node line
- ERROR: Invalid format for dependency graph
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/00a03c171e2c858b.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/pipeline/JSONOutputter.java:568
writer.write(Boolean.toString((Boolean) value));
} else if (int.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Integer.valueOf((int) value));
} else if (short.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Short.valueOf((short) value));
} else if (byte.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Byte.valueOf((byte) value));
} else if (long.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Long.valueOf((long) value));
} else if (char.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Character.valueOf((char) value));
} else if (float.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Float.valueOf((float) value));
} else if (double.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Double.valueOf((double) value));
} else if (boolean.class.isAssignableFrom(value.getClass())) {
routeObject(indent, Boolean.valueOf((boolean) value));
} else {
throw new RuntimeException("Unknown object to serialize: " + value);
}
}
public void object(int indent, Consumer<Writer> callback) {
writer.write("{");
final Pointer<Boolean> firstCall = new Pointer<>(true);
callback.accept((key, value) -> {
if (key != null && value != null) {
// First call overhead
if (!firstCall.dereference().orElse(false)) {
writer.write(",");
}
firstCall.set(false);
// Write the key
newline();
indent(indent + 1);
writer.write("\"");
writer.write(StringUtils.escapeJsonString(key));View on GitHub (pinned to 1b7edd19c4)