Hi Christian,
Thank you for your guidance! With the changes you describe the test case, and
the actual code, are working now. It is a helpful new feature to be able to
write JSON directly in XQuery.
Here is the updated test case which works with BaseX versions 11.4, 11.7, and
11.8-snapshot.
module namespace my = "test";
declare
%rest:POST("{$body}")
%rest:path("/my/function")
%rest:consumes('application/json')
%input:json('format=xquery')
%output:method("json")
function my:function (
$body
) {
message($body),
admin:write-log(json:serialize($body)),
let $items as xs:string* := array:flatten($body?items)
return string-join($items, ", ")
};
declare
%unit:test
function my:test () {
let $url := "http://localhost:8080/my/function"
let $body := { "items": [ ["item 1", "item 2", "item 3"] ] }
let $request :=
<http:request method="post" json="format=xquery,lax=true">
<http:header name="Content-Type" value="application/json"/>
<http:body media-type="application/json"/>
</http:request>
let $response := http:send-request($request, $url, $body)
return (
message($response, 'response: '),
unit:assert-equals($response[2], "item 1, item 2, item 3")
)
};
declare
%rest:error("*")
%rest:error-param('description', "{$description}")
%rest:error-param('code', "{$code}")
%rest:error-param('additional', "{$additional}")
%output:method("html")
function my:error(
$description as xs:string?,
$code as xs:string?,
$additional as item()*
) {
admin:write-log(string-join((
$code,
$description,
$additional =!> replace(replace(Q{java:org.basex.util.Prop}HOMEDIR(), '\\',
'/'), '', 'qi'),
string-join((request:path(), request:query()), '?')
), ' '), 'ERROR'),
web:response-header((), (), map{'status': 400}),
<p>{"An error occurred: " || $code || ", " || $description }</p>
};
I also observed that that the output of the web:create-url() function has
parameters in a different order using BaseX version 11.7 compared to earlier
versions. This minor change shouldn’t cause any problems, and it appears to be
an improvement related to the new feature for ordered maps.
Thank you!
Vincent
_____________________________________________
Vincent M. Lizzi
Head of Information Standards | Taylor & Francis Group
[email protected]<mailto:[email protected]>
Information Classification: General
From: Christian Grün <[email protected]>
Sent: Friday, January 31, 2025 4:35 PM
To: Lizzi, Vincent <[email protected]>
Cc: BaseX <[email protected]>
Subject: Re: [basex-talk] RESTXQ JSON parsing in BaseX 11.6
Thanks for the test case, Vincent,
Indeed it’s not RESTXQ, but the behavior of http:send-request that has changed:
Instead of passing a string representation of JSON to the function, you can
(well, need to) directly pass one of the BaseX JSON representations, either as
third function argument…
let $body := { "items": [ ["item 1", "item 2", "item 3"] ] }
let $request :=
<http:request method="post" json="format=xquery,lax=true">
<http:header name="Content-Type" value="application/json"/>
<http:body media-type="application/json"/>
</http:request>
let $response := http:send-request($request, $url, $body)
…or within the http:body element in the XML notation:
<http:body media-type="application/json">{
json:parse($json-string)
}</http:body>
As indicated in the first example, the 'map' keyword will become optional with
XQuery 4.0, so in many cases you can directly copy and paste JSON to your query.
Hope this helps,
Christian