How to convert JSON into SOAP

I need to convert JSON into SOAP but json comes in simplified and I need to add custom tags. So is there any way that I can modify the xml tags? e.g. { "hello" : "world" } become world

Solved Solved
0 2 4,439
1 ACCEPTED SOLUTION

OK I would do this in three steps:

  1. convert the JSON properties to "capitalized" forms. [JavaScript]
  2. convert the transformed JSON to XML [JSONToXML]
  3. transform the XML into the right structure with the namespace prefix and a namespace [XSL]

In the flow, this would look like this:

 

        <Step>
          <Name>JS-Convert-Property-Names</Name>
        </Step>
        <Step>
          <Name>J2X-Fee</Name>
        </Step>
        <Step>
          <Name>XSL-Reformat-and-Inject-Namespace</Name>
        </Step>

 

Attached is a working example.

Example invocation to demonstrate your case:

 

curl -i https://MYORG-MYENV.apigee.net/json-to-soap/t2 
HTTP/1.1 200 OK
Date: Wed, 13 Oct 2021 16:47:30 GMT
Content-Type: application/xml
Content-Length: 181
Connection: keep-alive

<cat:Fee xmlns:cat="mynamespace">
   <cat:FeeCode>123</cat:FeeCode>
   <cat:Quantity>1</cat:Quantity>
   <cat:FeeCode>345</cat:FeeCode>
   <cat:Quantity>1</cat:Quantity>
</cat:Fee>

 

I am certain that the example you showed me is not "the whole problem." So you'll need to adapt this example proxy to meet your needs. I'll leave that part to you.

----

Thinking about this further, you could do this in one step, using JavaScript callout, taking advantage of the E4X capability in the JavaScript. In other words you could do the three things : capitalize, convert to XML, and insert namespaces.... all in that one JavaScript module. the JS policy might look like this:

 

<Javascript name='JS-JSON-to-XML'>
  <Properties>
    <Property name='source-var'>contrivedMessage.content</Property>
    <Property name='output-var'>transformedContent</Property>
  </Properties>
  <ResourceURL>jsc://JSON-to-XML.js</ResourceURL>
</Javascript>

 

And the actual JS code would be like this:

 

function capitalize(s) {
  return s.charAt(0).toUpperCase() + s.slice(1);
}

var message = context.getVariable(properties['source-var']);
message = JSON.parse(message);
if (message && message.fee) {
  var xml = new XML("<Fee/>");
  var catNs = new Namespace('cat','urn:my-namespace-urn');
  xml.setNamespace(catNs);

  // the fee property is an array of children
  message.fee.forEach(function(item) {
     Object.keys(item).forEach(function(key){
       // feeCode, quantity, etc
       var elementName = capitalize(key);
       var s ='<'+ elementName+'>' + item[key] + '</'+ elementName+'>';
       var fragment = new XML(s);
       fragment.setNamespace(catNs);
       xml.appendChild(fragment);
    });
  });
  var s = xml.toXMLString();
  context.setVariable(properties['output-var'], s);
}

 

I've modified the attached example to include this option as well. My example invocation:

 

$ curl -i https://MYORG-MYENV.apigee.net/json-to-soap/t3
HTTP/1.1 200 OK
Date: Wed, 13 Oct 2021 21:23:21 GMT
Content-Type: application/xml
Content-Length: 185
Connection: keep-alive
APIProxy: json-to-soap r10

<cat:Fee xmlns:cat="urn:my-namespace-urn">
  <cat:FeeCode>123</cat:FeeCode>
  <cat:Quantity>1</cat:Quantity>
  <cat:FeeCode>345</cat:FeeCode>
  <cat:Quantity>1</cat:Quantity>
</cat:Fee>

 

View solution in original post

2 REPLIES 2

There are multiple ways to do what you are describing. Depending on your goals and your aptitudes, I'd recommend one over the other. All of them will work. Which you will prefer, depends on those inputs. Here's a summary.

  1. One way is to use AssignMessage. The AssignMessage configuration accepts a Payload element, which itself is a "message template". That means you can basically specify a "template" of what you want the resulting SOAP message to be, then within that template, insert references to the fields in the JSON payload. The result will be a correct SOAP message.

  2. If you'd prefer, you can use an XSLT sheet to do effectively the same thing. This is helpful when the resulting output SOAP message is of a non-determinant shape. For example, depending on the inbound (JSON) payload the output (SOAP) may be structured differently. You can use the xsl:if and xsl:choose mechanisms to accommodate this. XSLT is also helpful when there will be loops or repeats of an indeterminate size.

  3. e4X - which is a program model you can use from a JavaScript program to construct XML documents.

  4. Handlebars - or a similar templating model. This can be used from JavaScript, too.

If you show me the specific desired output SOAP message and a specific (actual) JSON inbound message, I can show you some examples of the above. But the actual JSON is probably not { "hello" : "world"}. Something a little more elaborate than that. Something closer to what you will actually use.

OK I would do this in three steps:

  1. convert the JSON properties to "capitalized" forms. [JavaScript]
  2. convert the transformed JSON to XML [JSONToXML]
  3. transform the XML into the right structure with the namespace prefix and a namespace [XSL]

In the flow, this would look like this:

 

        <Step>
          <Name>JS-Convert-Property-Names</Name>
        </Step>
        <Step>
          <Name>J2X-Fee</Name>
        </Step>
        <Step>
          <Name>XSL-Reformat-and-Inject-Namespace</Name>
        </Step>

 

Attached is a working example.

Example invocation to demonstrate your case:

 

curl -i https://MYORG-MYENV.apigee.net/json-to-soap/t2 
HTTP/1.1 200 OK
Date: Wed, 13 Oct 2021 16:47:30 GMT
Content-Type: application/xml
Content-Length: 181
Connection: keep-alive

<cat:Fee xmlns:cat="mynamespace">
   <cat:FeeCode>123</cat:FeeCode>
   <cat:Quantity>1</cat:Quantity>
   <cat:FeeCode>345</cat:FeeCode>
   <cat:Quantity>1</cat:Quantity>
</cat:Fee>

 

I am certain that the example you showed me is not "the whole problem." So you'll need to adapt this example proxy to meet your needs. I'll leave that part to you.

----

Thinking about this further, you could do this in one step, using JavaScript callout, taking advantage of the E4X capability in the JavaScript. In other words you could do the three things : capitalize, convert to XML, and insert namespaces.... all in that one JavaScript module. the JS policy might look like this:

 

<Javascript name='JS-JSON-to-XML'>
  <Properties>
    <Property name='source-var'>contrivedMessage.content</Property>
    <Property name='output-var'>transformedContent</Property>
  </Properties>
  <ResourceURL>jsc://JSON-to-XML.js</ResourceURL>
</Javascript>

 

And the actual JS code would be like this:

 

function capitalize(s) {
  return s.charAt(0).toUpperCase() + s.slice(1);
}

var message = context.getVariable(properties['source-var']);
message = JSON.parse(message);
if (message && message.fee) {
  var xml = new XML("<Fee/>");
  var catNs = new Namespace('cat','urn:my-namespace-urn');
  xml.setNamespace(catNs);

  // the fee property is an array of children
  message.fee.forEach(function(item) {
     Object.keys(item).forEach(function(key){
       // feeCode, quantity, etc
       var elementName = capitalize(key);
       var s ='<'+ elementName+'>' + item[key] + '</'+ elementName+'>';
       var fragment = new XML(s);
       fragment.setNamespace(catNs);
       xml.appendChild(fragment);
    });
  });
  var s = xml.toXMLString();
  context.setVariable(properties['output-var'], s);
}

 

I've modified the attached example to include this option as well. My example invocation:

 

$ curl -i https://MYORG-MYENV.apigee.net/json-to-soap/t3
HTTP/1.1 200 OK
Date: Wed, 13 Oct 2021 21:23:21 GMT
Content-Type: application/xml
Content-Length: 185
Connection: keep-alive
APIProxy: json-to-soap r10

<cat:Fee xmlns:cat="urn:my-namespace-urn">
  <cat:FeeCode>123</cat:FeeCode>
  <cat:Quantity>1</cat:Quantity>
  <cat:FeeCode>345</cat:FeeCode>
  <cat:Quantity>1</cat:Quantity>
</cat:Fee>