Title: Jackson 3: unguarded textValue()/asBoolean() throw where Jackson 2 returned defaults (JoinFunction, BooleanUtils) · Issue #434 · IBM/JSONata4Java · GitHub
Open Graph Title: Jackson 3: unguarded textValue()/asBoolean() throw where Jackson 2 returned defaults (JoinFunction, BooleanUtils) · Issue #434 · IBM/JSONata4Java
X Title: Jackson 3: unguarded textValue()/asBoolean() throw where Jackson 2 returned defaults (JoinFunction, BooleanUtils) · Issue #434 · IBM/JSONata4Java
Description: Summary Two unguarded coercion call sites changed behavior under the Jackson 3 migration (#430, PR #431). Jackson 3 tightened textValue() (now stringValue(), throws for any non‑String node) and the no‑arg asBoolean() (throws for non‑coer...
Open Graph Description: Summary Two unguarded coercion call sites changed behavior under the Jackson 3 migration (#430, PR #431). Jackson 3 tightened textValue() (now stringValue(), throws for any non‑String node) and the...
X Description: Summary Two unguarded coercion call sites changed behavior under the Jackson 3 migration (#430, PR #431). Jackson 3 tightened textValue() (now stringValue(), throws for any non‑String node) and the...
Opengraph URL: https://github.com/IBM/JSONata4Java/issues/434
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Jackson 3: unguarded textValue()/asBoolean() throw where Jackson 2 returned defaults (JoinFunction, BooleanUtils)","articleBody":"## Summary\n\nTwo unguarded coercion call sites changed behavior under the Jackson 3 migration (#430, PR #431). Jackson 3 tightened `textValue()` (now `stringValue()`, throws for **any** non‑String node) and the no‑arg `asBoolean()` (throws for non‑coercible node types). Jackson 2 returned `null` / `false` respectively. These lines were not changed by the migration, so behavior flipped from \"return default\" to \"throw `tools.jackson.databind.node.JsonNodeException`\".\n\nNot caught by the test suite.\n\n## Where \u0026 reproductions\n\n### 1. `JoinFunction.java:121` — `textValue()` on non‑string inner element\n\n```java\n} else if (element.isArray()) {\n for (Iterator\u003cJsonNode\u003e it = ((ArrayNode) element).iterator(); it.hasNext();) {\n stringJoiner.add(it.next().textValue()); // \u003c-- no isTextual() guard\n }\n}\n```\n\nNote the outer element at line 117 **is** guarded (`element.isTextual()`), but the inner loop at 121 is not.\n\n- Repro: `$join([[1, 2]])`\n- Jackson 2: `textValue()` returns `null` → `StringJoiner` appends `\"null\"` → result `\"nullnull\"`.\n- Jackson 3: **throws** `JsonNodeException`.\n\n### 2. `BooleanUtils.java:89` — `asBoolean()` on a `BinaryNode`\n\n```java\ncase BINARY:\n return node.asBoolean();\n```\n\n- Jackson 2: returns the default `false` for a `BinaryNode`.\n- Jackson 3: **throws** `JsonNodeException`.\n- Lower reachability (requires a `BinaryNode` reaching `$boolean(...)`), but it is an unguarded no‑arg coercion of exactly the kind this migration must audit.\n\n## Verified empirically against jackson‑databind 3.2.0\n\n```\nIntNode(5).textValue() -\u003e THROWS JsonNodeException\nBinaryNode.asBoolean() -\u003e THROWS JsonNodeException\n```\n\n## Related minor note (low priority)\n\n`ArrayUtils.compare` (line 105, changed in this PR) now uses `asText(\"\")`. For a container node this correctly restores the Jackson‑2 `\"\"`, but for a `POJONode` it returns `\"\"` where Jackson 2 returned the POJO's `toString()`. Reachability is very low ($sort over a regex `POJONode` is not a realistic user path), so this is noted rather than treated as a separate defect.\n\n## Suggested fix\n\nAdd an `isTextual()` guard at `JoinFunction:121` (matching line 117) — decide whether a non‑string inner element should stringify via the JSONata number/string rules or raise the existing `ERR_MSG_ARG1_ARR_STR`. For `BooleanUtils:89`, return `false` explicitly for the `BINARY` case rather than delegating to the now‑throwing `asBoolean()`.\n","author":{"url":"https://github.com/wnm3","@type":"Person","name":"wnm3"},"datePublished":"2026-07-07T16:39:27.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/434/JSONata4Java/issues/434"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:c59230a5-014d-04fa-1e24-e2932f9bc9fc |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | B47C:2C2A02:E5E949:13583F0:6A4F0267 |
| html-safe-nonce | c358d3bc7e84eb4f63d7da61afadd4268ac7f35a5a76f0f4645876a23f675d9c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCNDdDOjJDMkEwMjpFNUU5NDk6MTM1ODNGMDo2QTRGMDI2NyIsInZpc2l0b3JfaWQiOiI5MTkwMDk4OTQ4NDcxMDYzMTQzIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 94fda4e2c44b210d45d5159d6e64e54a1e2208bc4014d8dc79871f8cfefbd84c |
| hovercard-subject-tag | issue:4830453799 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/IBM/JSONata4Java/434/issue_layout |
| twitter:image | https://opengraph.githubassets.com/17ab3615a473bae8927c6a1372d105d3f2e88880bbb09491301c7bfb5a2e449f/IBM/JSONata4Java/issues/434 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/17ab3615a473bae8927c6a1372d105d3f2e88880bbb09491301c7bfb5a2e449f/IBM/JSONata4Java/issues/434 |
| og:image:alt | Summary Two unguarded coercion call sites changed behavior under the Jackson 3 migration (#430, PR #431). Jackson 3 tightened textValue() (now stringValue(), throws for any non‑String node) and the... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | wnm3 |
| hostname | github.com |
| expected-hostname | github.com |
| None | b92d11c0aa4a77d54ef4af1078b6a15fb5a70a215b30c4ecf28889d5a8e656d9 |
| turbo-cache-control | no-preview |
| go-import | github.com/IBM/JSONata4Java git https://github.com/IBM/JSONata4Java.git |
| octolytics-dimension-user_id | 1459110 |
| octolytics-dimension-user_login | IBM |
| octolytics-dimension-repository_id | 169904880 |
| octolytics-dimension-repository_nwo | IBM/JSONata4Java |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 169904880 |
| octolytics-dimension-repository_network_root_nwo | IBM/JSONata4Java |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 2b8f23afb982271f1b22258a94aede67a6b77760 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width