[bugfix] fn:json-to-xml: enforce option-parameter type & permitted-value checks (+~10 XQTS HEAD)#6351
[bugfix] fn:json-to-xml: enforce option-parameter type & permitted-value checks (+~10 XQTS HEAD)#6351joewiz wants to merge 3 commits into
Conversation
…value checks
Per F&O 3.1 section 2.4 (option parameter conventions) plus section 17.5.3:
* Wrong-typed option values now raise XPTY0004 (was: FOJS0005 for 'escape',
silently accepted for others).
* 'duplicates' values are checked against the permitted set {reject,
use-first, retain}; non-permitted values raise FOJS0005.
* 'validate' + 'duplicates: retain' is rejected as an incompatible
combination (FOJS0005).
* Unknown option keys on fn:json-to-xml raise FOJS0005.
* Empty-sequence option values trigger XPTY0004 (cardinality 0).
* 'fallback' arity is validated against the declared function signature.
Behavior under recognized, valid options is unchanged. Implementing the
'validate', 'escape', and 'fallback' semantics themselves is out of scope
and tracked in the parent triage report.
Targets ~11 fn-json-to-xml XQTS HEAD failures
(json-to-xml-error-018/019/020/021/022/023/024/025/026/040/041).
Refs F&O 3.1: https://www.w3.org/TR/xpath-functions-31/#options
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
XQTS HEAD spot-check (fn-json-to-xml)Ran
Matches the prediction in the parent triage report: Cat B (8) + Cat F (3) closed, no regressions in this test set. All 11 targeted error tests now pass: Spot-checked fn-parse-json and fn-json-doc separately — out of scope for this commit message but no regressions expected since the option-parsing code path is shared and behavior under recognized, valid options is unchanged. (Will post follow-up if those measurements differ.) |
Per F&O 3.1 section 2.4, option values undergo function-call-style coercion:
nodes are atomized to xs:untypedAtomic before the type check, which is
then cast to the declared type. Calling .atomize() on the item picks up
both element() and attribute() values that the previous strict-type
check was wrongly rejecting with XPTY0004.
Closes fn-parse-json-946 (XQTS HEAD) which uses
map { 'duplicates': <foo>reject</foo> }.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Follow-up: confirmed no regressions on sibling test sets and improved one additional case. After atomize fix (commit 873f28d), running
Vs. the baseline triage numbers, this PR closes −11 fn-json-to-xml plus −1 fn-parse-json ( The atomize fix is needed because F&O 3.1 §2.4 specifies option values undergo function-call-style coercion — node values atomize to |
Commit e3a2da8 introduced a single PERMITTED_DUPLICATES set {reject, use-first, retain} that was applied to both fn:parse-json and fn:json-to-xml. That regressed fn:parse-json calls using "use-last" (the XQSuite test arr:parse-json-duplicates use-last case) with FOJS0005 "value not permitted". Per F&O 3.1 the permitted values differ: * §17.4.1 fn:parse-json: "reject", "use-first", "use-last" https://www.w3.org/TR/xpath-functions-31/#func-parse-json * §17.5.1 fn:json-to-xml: "reject", "use-first", "retain" https://www.w3.org/TR/xpath-functions-31/#func-json-to-xml Both share "reject" and "use-first"; parse-json adds "use-last" (preserve last value), json-to-xml adds "retain" (keep duplicates in the XML output, incompatible with validate=true). Splits PERMITTED_DUPLICATES into per-function sets selected by the existing isJsonToXml flag. fn:json-doc shares fn:parse-json's option semantics (§17.4.4) and so picks up the parse-json permitted set, which is correct. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
[This response was co-authored with Claude Code. -Joe] Pushed Root cause: commit
The XQSuite test Fix: split into per-function permitted sets, selected by the existing Verification: local |
Summary
Enforce F&O 3.1 §2.4 (option-parameter conventions) and §17.5.3 on the options
map of
fn:json-to-xml(and, where shared,fn:parse-json/fn:json-doc):FOJS0005forescape, silently accepted forvalidate,liberalwith non-boolean, etc.).duplicatesis checked against the permitted set{reject, use-first, retain}; non-permitted values raise FOJS0005.validate: true()combined withduplicates: 'retain'raises FOJS0005.fn:json-to-xmlraise FOJS0005.fallback's declared typefunction(xs:string) as xs:stringis validatedfor arity (=1).
Behavior under recognized, valid options is unchanged — implementing the
validate,escape: true(), andfallbacksemantics themselves is out ofscope (tracked separately).
What Changed
exist-core/src/main/java/org/exist/xquery/functions/fn/JSON.javaparseOptions(...)helper andrequireBooleanOpt/requireStringOpt/requireFunctionOpthelpers implement stricttype-checking per F&O §2.4 (no XPath promotion;
xs:untypedAtomiciscast; everything else is rejected with
XPTY0004).rejectUnknownJsonToXmlOptionsenforces the closed option set forfn:json-to-xml.NPath complexity below the PMD threshold.
exist-core/src/test/xquery/xquery3/json-to-xml.xqljson-to-xml-error-2(escape non-boolean) fromFOJS0005toXPTY0004.type mismatches, duplicates permitted values, validate+retain incompat,
and unknown option keys.
Spec References
fn:parse-json/fn:json-to-xml:https://www.w3.org/TR/xpath-functions-31/#func-json-to-xml
https://www.w3.org/TR/xpath-functions-31/#options
XQTS HEAD targets
escape:'unrecognised')liberal:'something')validate:())validate:(true,true))validate:'EMCA-262')escape:())escape:(true,true))escape:'EMCA-262')fallback:'dummy')fallback:concat#2)XQTS spot-check rerun pending; will update this table once measured.
Sibling fix: #6350 (fn:xml-to-json validation).
Test Plan
mvn test -pl exist-core -Dtest=xquery.xquery3.XQuery3Tests—1020 / 1020 passing (1 skipped, pre-existing).
JSON.java— no new findings; pre-existingparseResource/readValueNPath warnings unchanged.fn-json-to-xmlspot-check (rebuild runner permeasurement SOP, expect Cat B closed, Cat F partial).