Skip to main content

Version: 3.9.0

Convert JSON to XML

XML (eXtensible Markup Language) is a widely adopted standard for representing and organizing structured data. With its flexibility and human-readable syntax, XML provides a versatile solution for data interchange and storage across diverse systems and platforms. It is also used by SOAP protocol as its message format.

This guide will show you how to convert between JSON and XML SOAP using the body-transformer plugin, which allows client to send and receive JSON data while interacting with the SOAP service.


JSON to XML Diagram

Prerequisite(s)

Deploy an Example SOAP Server

Start an example SOAP server that exposes data from various European countries:

cd /tmp
git clone https://github.com/spring-guides/gs-soap-service.git
cd gs-soap-service/complete
./mvnw spring-boot:run

Create Transformation Templates

The transformation template mainly uses lua-resty-template syntax. See template syntax for more information.

Additionally, there are a few auxiliary functions which you can use in templates:

  • _escape_json() and _escape_xml() - used to escape special characters, such as double quotes
  • _body - used to access request body
  • _ctx - used to access context variables

Create request and response transformation templates, which are customized and to be configured in the body-transformer plugin to instruct on how to transcode between XML and JSON:

req_template=$(cat <<EOF | awk '{gsub(/"/,"\\\"");};1' | awk '{$1=$1};1' | tr -d '\r\n'
<?xml version="1.0"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns0:getCountryRequest xmlns:ns0="http://spring.io/guides/gs-producing-web-service">
<ns0:name>{{_escape_xml(name)}}</ns0:name>
</ns0:getCountryRequest>
</soap-env:Body>
</soap-env:Envelope>
EOF
)

rsp_template=$(cat <<EOF | awk '{gsub(/"/,"\\\"");};1' | awk '{$1=$1};1' | tr -d '\r\n'
{% if Envelope.Body.Fault == nil then %}
{
"status":"{{_ctx.var.status}}",
"currency":"{{Envelope.Body.getCountryResponse.country.currency}}",
"population":{{Envelope.Body.getCountryResponse.country.population}},
"capital":"{{Envelope.Body.getCountryResponse.country.capital}}",
"name":"{{Envelope.Body.getCountryResponse.country.name}}"
}
{% else %}
{
"message":{*_escape_json(Envelope.Body.Fault.faultstring[1])*},
"code":"{{Envelope.Body.Fault.faultcode}}"
{% if Envelope.Body.Fault.faultactor ~= nil then %}
, "actor":"{{Envelope.Body.Fault.faultactor}}"
{% end %}
}
{% end %}
EOF
)

Configure APISIX

Create a route with body-transformer referencing the transformation templates created previously:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "body-transformer-route",
"methods": ["POST"],
"uri": "/ws",
"plugins": {
"body-transformer": {
"request": {
"template": "'"$req_template"'",
"input_format": "json"
},
"response": {
"template": "'"$rsp_template"'",
"input_format": "xml"
}
},
"proxy-rewrite": {
"headers": {
"set": {
"Content-Type": "text/xml"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"localhost:8080": 1
}
}
}'

❶ Set the request input format as JSON, so that the plugin will apply the JSON decoder internally.

❷ Set the response input format as XML, so that the plugin will apply the XML decoder internally.

❸ Set the Content-Type header to text/xml for the upstream service to respond properly.

tip

If it is cumbersome to adjust complex text files to be valid transformation templates, you can use the base64 utility to encode the files, such as the following:

"body-transformer": {
"request": {
"template": "'"$(base64 -w0 /path/to/request_template_file)"'"
},
"response": {
"template": "'"$(base64 -w0 /path/to/response_template_file)"'"
}
}

Verify

Send a request to the route with a valid JSON body:

curl "http://127.0.0.1:9080/ws" -X POST -d '{"name": "Spain"}'

You should see a response similar to the following:

{
"status": "200",
"currency": "EUR",
"population": 46704314,
"capital": "Madrid",
"name": "Spain"
}

This shows that the JSON body sent in the request has been transformed into XML and forwarded to the upstream SOAP service, and the response body was transformed back from XML to JSON.

Next Steps

The body-transformer plugin can also be used for transformation between YAML and JSON, or modification of the request bodies. See the plugin doc for more information.


API7.ai Logo

API Management for Modern Architectures with Edge, API Gateway, Kubernetes, and Service Mesh.

Product

API7 Cloud

SOC2 Type IRed Herring

Copyright © APISEVEN Ltd. 2019 – 2024. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the

Apache Software Foundation