Skip to content

Commit 74a5aa0

Browse files
Implement error collection for deserialization (#1196) (#5364)
1 parent 3784b87 commit 74a5aa0

File tree

8 files changed

+1732
-2
lines changed

8 files changed

+1732
-2
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).problemCollectingReader();
608+
609+
try {
610+
Order result = reader.readValueCollectingProblems(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 problems 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).problemCollectingReader(10); // limit to 10
627+
```
628+
629+
Few things to keep in mind:
630+
631+
1. This is best-effort: not all problems 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 `readValueCollectingProblems()` gets its own problem 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) during the attempt, but if any problems are collected, only the problems are reported in the `DeferredBindingException` - the partial result is not returned.
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/CREDITS

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ Fouad Almalki (@Eng-Fouad)
113113
with Jackson 3
114114
[3.0.3]
115115

116+
Oliver Drotbohm (@odrotbohm)
117+
* Requested #1196: Add opt-in error collection for deserialization
118+
[3.1.0]
119+
120+
@sri-adarsh-kumar
121+
* Contributed #1196: Add opt-in error collection for deserialization
122+
[3.1.0]
123+
116124
Hélios Gilles (@RoiSoleil)
117125
* Contributed #5413: Add/support forward reference resolution for array values
118126
[3.1.0]
127+
128+

release-notes/VERSION

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ Versions: 3.x (for earlier see VERSION-2.x)
77

88
3.1.0 (not yet released)
99

10+
#1196: Add opt-in error collection for deserialization
11+
(requested by @odrotbohm)
12+
(contributed by @sri-adarsh-kumar)
1013
#5350: Add `DeserializationFeature.USE_NULL_FOR_MISSING_REFERENCE_VALUES` for
1114
selecting `null` vs "empty/absent" value when deserializing missing `Optional` value
1215
#5361: Fix Maven SBOM publishing (worked in 3.0.0-rc4 but not in rc5 or later)

0 commit comments

Comments
 (0)