Skip to content

Commit bbec6ed

Browse files
Add documentation for error collection feature (#1196)
- Add release notes entry in VERSION for 3.1.0 - Add tutorial section in README.md matching existing tone - Explain problem: fix-retry cycle vs collecting all errors at once - Show basic usage with code examples - Document DoS protection with 100 error default limit - Clarify best-effort nature and what can/cannot be collected - Document JSON Pointer paths (RFC 6901) for error locations - Explain thread-safe per-call error buckets - List practical use cases: API validation, batch processing, tooling Addresses 9-year-old feature request from Oliver Drotbohm covering key concerns from discussion: DoS protection, thread safety, recoverable errors, and error reporting. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent b7fbb39 commit bbec6ed

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

README.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,60 @@ This will deserialize JSON fields with `known_as`, as well as `identifer` and `f
581581
Note: to use the `@JsonAlias` annotation, a `@JsonProperty` annotation must also be used.
582582

583583
Overall, Jackson library is very powerful in deserializing objects using builder pattern.
584-
584+
585+
## Tutorial: Collecting multiple errors (3.1+)
586+
587+
One recently introduced feature is the ability to collect multiple deserialization errors instead of failing fast on the first one. This can be really handy for validation use cases.
588+
589+
By default, if Jackson encounters a problem during deserialization -- say, string `"xyz"` for an `int` property -- it will immediately throw an exception and stop. But sometimes you want to see ALL the problems in one go.
590+
591+
Consider a case where you have a couple of fields with bad data:
592+
593+
```java
594+
class Order {
595+
public int orderId;
596+
public Date orderDate;
597+
public double amount;
598+
}
599+
600+
String json = "{\"orderId\":\"not-a-number\",\"orderDate\":\"bad-date\",\"amount\":\"xyz\"}";
601+
```
602+
603+
Normally you'd get an error about `orderId`, fix it, resubmit, then get error about `orderDate`, and so on. Not fun. So let's collect them all:
604+
605+
```java
606+
ObjectMapper mapper = new JsonMapper();
607+
ObjectReader reader = mapper.readerFor(Order.class).collectErrors();
608+
609+
try {
610+
Order result = reader.readValueCollecting(json);
611+
// worked fine
612+
} catch (DeferredBindingException ex) {
613+
System.out.println("Found " + ex.getProblems().size() + " problems:");
614+
for (CollectedProblem problem : ex.getProblems()) {
615+
System.out.println(problem.getPath() + ": " + problem.getMessage());
616+
// Can also access problem.getRawValue() to see what the bad input was
617+
}
618+
}
619+
```
620+
621+
This will report all 3 problems at once. Much better.
622+
623+
By default, Jackson will collect up to 100 errors before giving up (to prevent DoS-style attacks with huge bad payloads). You can configure this:
624+
625+
```java
626+
ObjectReader reader = mapper.readerFor(Order.class).collectErrors(10); // limit to 10
627+
```
628+
629+
Few things to keep in mind:
630+
631+
1. This is best-effort: not all errors can be collected. Malformed JSON (like missing closing brace) or other structural problems will still fail immediately. But type conversion errors, unknown properties (if you enable that check), and such will be collected.
632+
2. Error paths use JSON Pointer notation (RFC 6901): so `"/items/0/price"` means first item in `items` array, `price` field. Special characters get escaped (`~` becomes `~0`, `/` becomes `~1`).
633+
3. Each call to `readValueCollecting()` gets its own error bucket, so it's thread-safe to reuse the same `ObjectReader`.
634+
4. Fields that fail to deserialize get default values (0 for primitives, null for objects), so you do get a result object back (thrown in the exception).
635+
636+
This is particularly useful for things like REST API validation (return all validation errors to client), or batch processing (log errors but keep going), or development tooling.
637+
585638
# Contribute!
586639

587640
We would love to get your contribution, whether it's in form of bug reports, Requests for Enhancement (RFE), documentation, or code patches.

release-notes/VERSION

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ Versions: 3.x (for earlier see VERSION-2.x)
55
=== Releases ===
66
------------------------------------------------------------------------
77

8+
3.1.0 (NOT YET RELEASED)
9+
10+
#1196: Add opt-in error collection for deserialization
11+
(requested by @odrotbohm, contributed by @sri-adarsh-kumar)
12+
813
3.0.1 (21-Oct-2025)
914

1015
#5335: JsonMapper to deserialize `Optional.empty()` instead of `null`

0 commit comments

Comments
 (0)