rest > soap ; variable extraction ; from json payload to soap envelope?

Not applicable

So, I'm working with a third party soap service and we are trying to expose it as Rest using Apigee.

It is working for simple calls exposed as Rest GET.

When many parameters needs to be passed, we use a Rest POST json payload.

For example, if we use the famous weather soap service as an example, we would want to turn this json from our Rest POST call…:

{
	"ZIP":"07030"
}

…into that soap XML sent to the third party service.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><GetCityWeatherByZIP xmlns="http://ws.cdyne.com/WeatherWS/"><ZIP>07030</ZIP></GetCityWeatherByZIP></soap:Body></soap:Envelope>

It works perfectly fine, we use this kind of policy with some jsonpath:

<ExtractVariables async="false" continueOnError="true" enabled="true" name="GetCityWeatherByZIP-extract-form-param">
    <DisplayName>GetCityWeatherByZIP Extract Form Param</DisplayName>
    <Source clearPayload="true|false">request</Source>
    <JSONPayload>
        <Variable name="ZIP" type="string">
            <JSONPath>$.ZIP</JSONPath>
        </Variable>
    </JSONPayload>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</ExtractVariables>

=====

However, in some cases, the calls and their payloads are more complicated, involving nested structures and arrays (because the third party service is like that). We are not too sure what is the best way to extract a list of a values from a json array and populate the corresponding section of a soap xml envelope, for example, if we want to turn this:

{
	"apiSessionId":"123456",
	"calendarId":"111",
	"userId":"222",
	"slots":[
		1,
		2,
		3
    ]
}

into this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://www.q.com/Services" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:LockSlots>
         <ser:apiSessionId>123456</ser:apiSessionId>
         <ser:calendarId>111</ser:calendarId>
         <ser:userId>222</ser:userId>
         <ser:slots>
            <arr:short>1</arr:short>
            <arr:short>2</arr:short>
            <arr:short>3</arr:short>
         </ser:slots>
      </ser:LockSlots>
   </soapenv:Body>
</soapenv:Envelope>

How would you do it? Is it possible with just jsonpath and policies? Do we need to use something else like javascript? Many Thanks

Solved Solved
1 3 1,682
1 ACCEPTED SOLUTION

Not applicable

Hi Mikael,

For this you are not going to be able to do it with just jsonpath and policies. You definitely could use javascript to do it, but you would have to deal with the complexity around elements with multiple occurrences as well as with optional elements.

Optional ones should be straight forward, you would just need to check for the existence of a variable and if it is there then add in the element to the soap payload. For elements with multiple occurrences then you'd need to use involve some sort of for each loop, and for each value, create a new element in the payload.

You could also explore using XSLT to do this, and that might be a more elegant solution.

View solution in original post

3 REPLIES 3

Not applicable

Hi Mikael,

For this you are not going to be able to do it with just jsonpath and policies. You definitely could use javascript to do it, but you would have to deal with the complexity around elements with multiple occurrences as well as with optional elements.

Optional ones should be straight forward, you would just need to check for the existence of a variable and if it is there then add in the element to the soap payload. For elements with multiple occurrences then you'd need to use involve some sort of for each loop, and for each value, create a new element in the payload.

You could also explore using XSLT to do this, and that might be a more elegant solution.

Hello, Thanks for your help.

Actually, since I posted this message, I used javascript in Apigee to do a very custom json transformation at PostProxy time, for a different project not involving soap at all.

What I wonder is, if I use such a javascript solution here, where should the manually created soap envelop go?

In my existing json transformation case, I do this:

var originalResponse = JSON.parse(context.proxyResponse.content);
//... lots of changes here ...
context.proxyResponse.content = JSON.stringify(modifiedResponse, null, '\t');

What would be the equivalent of that last line in a "Pre" scenario, sending to a soap target? Thanks!

Hi Mikael,

Depending on whether you are running the JavaScript in the target or the proxy flow then you need to set it to either context.targetRequest.body or to context.proxyRequest.body.

You can refer to http://docs.apigee.com/api-services/reference/javascript-object-model for detail about the JavaScript object model.