Reputation: 190
I am trying to send JSON via a POST request from eXist-db to an API using the eXPath HTTP-Module, but I'm always recieving the following Error:
exerr:ERROR Error serializing the body content
My XQuery looks like:
xquery version "3.1";
declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";
let $payload := map {
"name": "testuser",
"role": "user"
}
return
hc:send-request(
<hc:request method='post'>
<hc:body media-type="application/json"/>
</hc:request>,
'https://reqres.in/api/users',
serialize($payload, <output:serialization-parameters>
<output:method>json</output:method>
</output:serialization-parameters>)
)[2] => util:base64-decode() => parse-json()
Expected Output (tested via Postman):
{
"name": "testuser",
"id": "820",
"createdAt": "2021-06-03T05:50:32.049Z"
}
How do i serialize content to JSON and send it via a POST-request from eXist-db? The solution prompted here is not working for me.
Upvotes: 3
Views: 525
Reputation: 1337
Here is the reformated version with the parameters broken out into their individual variables from Joe's answer.
xquery version "3.1";
let $payload := map {
"name": "testuser",
"role": "user"
}
let $request :=
<hc:request method='post'>
<hc:body method="text" media-type="application/json"/>
</hc:request>
let $href := 'https://reqres.in/api/users'
let $bodies := fn:serialize($payload, map { "method": "json" })
return
hc:send-request($request, $href, $bodies)[2] => util:base64-decode() => parse-json()
Upvotes: 1
Reputation: 5294
The solution is to add @method="text"
to the <body>
element.
This attribute is documented in the EXPath HTTP Client spec, section 3.2 Serializing the request content:
The default value of the serialization method depends on the media-type: it is
xml
if it is an XML media type,html
if it is an HTML media type,xhtml
if it is application/xhtml+xml,text
if it is a textual media type, andbinary
for any other case.
What this means is that the EXPath HTTP Client doesn't have a built-in mapping for the media-type of application/json
—i.e., it falls back on binary
. But JSON is a textual media type, and you've already performed the serialization of your XDM map into text via the fn:serialize()
function. So you have to override the EXPath HTTP Client default of method="binary"
and set method="text"
on the <body>
element.
The draft v2 spec, simplifies sending JSON; by default, when it detects that the body contains a map()
or array()
, it will serialize the item as JSON, with the appropriate media-type.
But for now with v1, we still need to explicitly (1) serialize maps and arrays using the JSON serialization method and (2) specify method="text"
on the <body>
element.
Upvotes: 4