Skip to content

(javax-money) Fail cleanly on non-Object input instead of throwing NullPointerException - #91

Open
pjfanning wants to merge 2 commits into
FasterXML:3.xfrom
pjfanning:fix-javax-money-non-object-input
Open

(javax-money) Fail cleanly on non-Object input instead of throwing NullPointerException#91
pjfanning wants to merge 2 commits into
FasterXML:3.xfrom
pjfanning:fix-javax-money-non-object-input

Conversation

@pjfanning

Copy link
Copy Markdown
Member

Problem

MonetaryAmountDeserializer.deserialize() assumes it is positioned on a START_OBJECT:

while (parser.nextToken() != JsonToken.END_OBJECT) {
    final String field = parser.currentName();

    parser.nextToken();

    if (field.equals(names.getAmount())) {

For any non-Object input, currentName() returns null and the very next line dereferences it. A bare NPE escapes to the caller instead of a JacksonException:

input read as MonetaryAmount before
12 NullPointerException: Cannot invoke "String.equals(Object)" because "field" is null
"abc" same
[1,2] same

moneta's FastMoney / Money / RoundedMoney deserializers share this class, so they are affected too.

Fix

Check the token up front — the same thing joda-money's MoneyDeserializer already does — and only loop while actually positioned on a PROPERTY_NAME, so malformed content cannot fall into the same trap:

Cannot deserialize value of type `javax.money.MonetaryAmount` from Integer value ...

Also removes a duplicated import javax.money.CurrencyUnit; import javax.money.MonetaryAmount; pair at the top of the file.

Tests

New FailOnNonObjectTest (7 cases): number/string/array/empty-array input, a bad element inside a List<MonetaryAmount>, plus checks that valid Objects and explicit null still deserialize.

javax-money 142 tests and moneta 137 tests all green.

pjfanning and others added 2 commits September 9, 2026 10:12
`MonetaryAmountDeserializer.deserialize()` assumes it is positioned on a
START_OBJECT and loops with:

    while (parser.nextToken() != JsonToken.END_OBJECT) {
        final String field = parser.currentName();
        ...
        if (field.equals(names.getAmount())) {

For any non-Object input `currentName()` returns `null`, so a bare
`NullPointerException: Cannot invoke "String.equals(Object)" because "field"
is null` escapes to the caller rather than a `JacksonException`. Inputs `12`,
`"abc"` and `[1,2]` all reproduce it, and `moneta`'s `FastMoney`/`Money`/
`RoundedMoney` deserializers share this class.

Verify the token up front (as joda-money's `MoneyDeserializer` already does),
and only loop while positioned on a PROPERTY_NAME so malformed content cannot
fall into the same trap. Also drop a duplicated import pair.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant