Skip to content

Honor @JsonView in ThrowableDeserializer.deserializeFromObject() - #6174

Merged
cowtowncoder merged 4 commits into
FasterXML:3.1from
aysha-afrah26:throwable-view-bypass
Sep 4, 2026
Merged

Honor @JsonView in ThrowableDeserializer.deserializeFromObject()#6174
cowtowncoder merged 4 commits into
FasterXML:3.1from
aysha-afrah26:throwable-view-bypass

Conversation

@aysha-afrah26

Copy link
Copy Markdown
Contributor

BeanDeserializer and its array and builder variants skip properties that fall outside the active @JSONVIEW, but ThrowableDeserializer overrides deserializeFromObject on its own to handle the special message and cause construction, and that override never looked at the view. It only bites exceptions that reach this loop rather than the property-based-creator path: a Throwable with a default constructor and no @JsonCreator, where the remaining fields are plain setters. Under a restricted view those fields are still read straight from input, so a property that belongs only to another view (say an internal-only field on a custom exception) gets populated by a caller reading under a narrower view. I noticed it while checking which deserializers consult _needViewProcesing and this was the only property loop that did not. The fix reads the active view once and skips any property not visible in it before the value is set or deferred, matching what deserializeWithView already does, including the FAIL_ON_UNEXPECTED_VIEW_PROPERTIES behavior. I kept the change inside deserializeFromObject so the creator and any-setter paths are untouched.

@github-actions

Copy link
Copy Markdown

🧪 Code Coverage Report

Metric Coverage Change
Instructions coverage 81.42% 📉 -0.010%
Branches branches 74.76% 📈 +0.000%

Coverage data generated from JaCoCo test results

@cowtowncoder cowtowncoder changed the title honor @JsonView in ThrowableDeserializer.deserializeFromObject Honor @JsonView in ThrowableDeserializer.deserializeFromObject() Aug 31, 2026
@cowtowncoder cowtowncoder added the cla-received PR already covered by CLA (optional label) label Aug 31, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

🧪 Code Coverage Report

Metric Coverage Change
Instructions coverage 81.42% 📉 -0.020%
Branches branches 74.76% 📉 -0.010%

Coverage data generated from JaCoCo test results

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

🧪 Code Coverage Report

Metric Coverage Change
Instructions coverage 81.43% 📉 -0.010%
Branches branches 74.77% 📈 +0.010%

Coverage data generated from JaCoCo test results

@cowtowncoder

cowtowncoder commented Sep 4, 2026

Copy link
Copy Markdown
Member

This may be problematic for common use cases due to 3.x enabling of MapperFeature.DEFAULT_VIEW_INCLUSION by default -- we do NOT want to start dropping standard properties like cause or localizedMessage just because they have no @JsonView associated. So basically Throwables are not regular POJOs; only sub-type properties should follow view-limitations.

EDIT: apparently only problematic with stackTrace

@cowtowncoder cowtowncoder added this to the 3.1.7 milestone Sep 4, 2026
Comment on lines +329 to +339
private boolean _isStandardThrowableProperty(String propertyName) {
switch (propertyName) {
case PROP_NAME_CAUSE:
case PROP_NAME_STACK_TRACE:
case PROP_NAME_MESSAGE:
case PROP_NAME_LOCALIZED_MESSAGE:
case PROP_NAME_SUPPRESSED:
return true;
default:
return false;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Edge Case: Standard-prop exemption bypassed by property naming strategy

_isStandardThrowableProperty matches property names with a case-sensitive switch on the literal Throwable names (cause, stackTrace, etc.). Under a PropertyNamingStrategy that renames properties (e.g. upper-camel), prop.getName() no longer equals these literals, so the standard property is not exempted and would again be filtered out under a restricted view. This is consistent with the pre-existing naming-strategy limitation noted at the message handling (databind#3497), so it is a minor gap rather than a regression; if broader coverage is desired, compare against the mangled names as done elsewhere.

Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Code Review 👍 Approved with suggestions 0 resolved / 1 findings

Fixes @JsonView bypass in ThrowableDeserializer.deserializeFromObject() by checking the active view before populating properties, matching the behavior of BeanDeserializer. Consider that _isStandardThrowableProperty uses case-sensitive literal matching and may not recognize properties renamed by a PropertyNamingStrategy, causing standard properties to be filtered under a restricted view—a minor gap consistent with existing naming-strategy limitations noted in databind#3497.

💡 Edge Case: Standard-prop exemption bypassed by property naming strategy

📄 src/main/java/tools/jackson/databind/deser/jdk/ThrowableDeserializer.java:329-339 📄 src/main/java/tools/jackson/databind/deser/jdk/ThrowableDeserializer.java:135-136

_isStandardThrowableProperty matches property names with a case-sensitive switch on the literal Throwable names (cause, stackTrace, etc.). Under a PropertyNamingStrategy that renames properties (e.g. upper-camel), prop.getName() no longer equals these literals, so the standard property is not exempted and would again be filtered out under a restricted view. This is consistent with the pre-existing naming-strategy limitation noted at the message handling (databind#3497), so it is a minor gap rather than a regression; if broader coverage is desired, compare against the mangled names as done elsewhere.

🤖 Prompt for agents
Code Review: Fixes `@JsonView` bypass in `ThrowableDeserializer.deserializeFromObject()` by checking the active view before populating properties, matching the behavior of `BeanDeserializer`. Consider that `_isStandardThrowableProperty` uses case-sensitive literal matching and may not recognize properties renamed by a `PropertyNamingStrategy`, causing standard properties to be filtered under a restricted view—a minor gap consistent with existing naming-strategy limitations noted in databind#3497.

1. 💡 Edge Case: Standard-prop exemption bypassed by property naming strategy
   Files: src/main/java/tools/jackson/databind/deser/jdk/ThrowableDeserializer.java:329-339, src/main/java/tools/jackson/databind/deser/jdk/ThrowableDeserializer.java:135-136

   `_isStandardThrowableProperty` matches property names with a case-sensitive `switch` on the literal Throwable names (`cause`, `stackTrace`, etc.). Under a `PropertyNamingStrategy` that renames properties (e.g. upper-camel), `prop.getName()` no longer equals these literals, so the standard property is not exempted and would again be filtered out under a restricted view. This is consistent with the pre-existing naming-strategy limitation noted at the `message` handling (databind#3497), so it is a minor gap rather than a regression; if broader coverage is desired, compare against the mangled names as done elsewhere.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@cowtowncoder

Copy link
Copy Markdown
Member

Changed to include "standard" properties regardless.

@cowtowncoder
cowtowncoder merged commit a768722 into FasterXML:3.1 Sep 4, 2026
5 checks passed
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

🧪 Code Coverage Report

Metric Coverage Change
Instructions coverage 81.44% 📈 +0.000%
Branches branches 74.76% 📈 +0.000%

Coverage data generated from JaCoCo test results

cowtowncoder added a commit to aysha-afrah26/jackson-databind that referenced this pull request Sep 4, 2026
Conflict: `ThrowableDeserializer` import block -- FasterXML#6174 (`@JsonView`)
added `ClassUtil`, this branch added `IgnorePropertiesUtil`; keep both.
The two changes touch different parts of `deserializeFromObject()`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ViTmN932ZXuhpABmeGa6L9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-received PR already covered by CLA (optional label)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants