AWS API Gateway : Convert response to XML - amazon-web-services

I am getting a string value (xml to string) from lambda backend which should be returned to end user in application/xml format. How can I achieve this?

You can specify an Integration Response that returns XML, along with a mapping template to format XML using the object returned from Lambda.
I do not believe there is a default format conversion to XML. A simple mapping template might be like this:
#set($root = $input.path('$'))
<stuff>
<message>$root.message</message>
<sourceIp>$context.identity.sourceIp</sourceIp>
<outputs>
#foreach($key in $root.keySet())
<output>
<key>$key</key>
<value>$root.get($key)</value>
</output>
#end
</outputs>
</stuff>

With reference to this document, section "Accessing the $util Variable", solved the challenge in a simple JSON to XML transform. I did try the mapping template given earlier here, but it did not work for me.
In my case, my JSON response payload is of the form:
[
{
"key1": "val1",
"key2": "val2",
"key3": "val3"
},
{
"key1": "val1",
"key2": "val2",
"key3": "val3",
"key4": "val4"
}
]
Here is the mapping template that deals with it:
#set ($arr = $util.parseJson($input.path('$')))
<responses>
#foreach($c in $arr)
<response>
#foreach ($k in $c.keySet())
<$k>$c.get($k)</$k>#end
</response>
#end
</responses>
The key was the parseJson to get a true JSON/Java object. After thi it was smooth sailing.
And the output is of the form:
<responses>
<response>
<key1>val1</key1>
...
</response>
...
</responses>
I hope this helps.

Related

Optional print tag xml and optional tag without value

i need little help about how the request field when no value or optional with condition can print at response. i have request json message and want convert to xml with wso2.
sample request
"AppHdr" : {
"Fr" : {
"FIId" : {
"FinInstnId" : {
"Othr" : {
"Id" : "FASTIDJA"
}
}
}
},
"To" : {
"FIId" : {
"FinInstnId" : {
"Othr" : {
"Id" : "INDOIDJA"
}
}
}
},
"BizMsgIdr" : "20210301FASTIDJA010HRB12345678",
"MsgDefIdr" : "pacs.002.001.10",
"BizSvc" : "",
"CreDt" : "2021-03-01T12:00:00",
"CpyDplct" : "",
"PssblDplct" : "",
"Sgntr" : ""
},
the result response need to fix was like this
<ns:AppHdr>
<ns1:Fr>
<ns1:FIId>
<ns1:FinInstnId>
<ns1:Othr>
<ns1:Id>FASTIDJA</ns1:Id>
</ns1:Othr>
</ns1:FinInstnId>
</ns1:FIId>
</ns1:Fr>
<ns1:To>
<ns1:FIId>
<ns1:FinInstnId>
<ns1:Othr>
<ns1:Id>INDOIDJA</ns1:Id>
</ns1:Othr>
</ns1:FinInstnId>
</ns1:FIId>
</ns1:To>
<ns1:BizMsgIdr>20210301FASTIDJA010HRB12345678</ns1:BizMsgIdr>
<ns1:MsgDefIdr>pacs.002.001.10</ns1:MsgDefIdr>
<ns1:CreDt>2021-03-01T12:00:00Z</ns1:CreDt>
</ns:AppHdr>
need hint for my case like this. thanks
You could use XSLT to convert from JSON to XML. [1][2]
Normally people want to eliminate empty tags and you know they are possible from the Schema. But in instances where you want an empty tag you can use the attribute xls:nil=true feature. [3]
[1] https://docs.wso2.com/display/EI660/Sample+440%3A+Converting+JSON+to+XML+Using+XSLT
[2] https://docs.wso2.com/display/EI660/XSLT+Mediator+
[3] https://www.ibm.com/support/pages/how-set-empty-element-attribute-xslniltrue-using-xslt
The easiest way to convert a JSON to XML is by setting the messageType property. For example, check the below.
<property name="messageType" scope="axis2" type="STRING" value="application/xml"/>
Setting the above property alone will Convert your Json to the following XML.
<AppHdr>
<Fr>
<FIId>
<FinInstnId>
<Othr>
<Id>FASTIDJA</Id>
</Othr>
</FinInstnId>
</FIId>
</Fr>
<To>
<FIId>
<FinInstnId>
<Othr>
<Id>INDOIDJA</Id>
</Othr>
</FinInstnId>
</FIId>
</To>
<BizMsgIdr>20210301FASTIDJA010HRB12345678</BizMsgIdr>
<MsgDefIdr>pacs.002.001.10</MsgDefIdr>
<BizSvc></BizSvc>
<CreDt>2021-03-01T12:00:00</CreDt>
<CpyDplct></CpyDplct>
<PssblDplct></PssblDplct>
<Sgntr></Sgntr>
</AppHdr>
Other than that you can use JSON Transform Mediator. Here you can control how the transformation handles Null values by setting different synapse properties. If you want fine control over the transformation. You can use the Datamapper Mediator, XSLT transformation or manually construct the Payload using the PayloadFactory mediator.

AWS API Gateway template mapping for Kinesis stream

As per aws tutorial the kinesis stream PutRecord expects base64encoded JSON string as data.
In my case I need to create an object inside the template mapping for integration request before it gets to the kinesis stream.
Code example from API gateway template mapper:
#set($inputRoot = $input.path('$'))
#set($data = {
"session": "$inputRoot.session",
"customer": "$inputRoot.customer",
"ip": "$context.identity.sourceIp"
})
{
"StreamName": "metrics-stream",
"Data": "$util.base64Encode($data)",
"PartitionKey": "$input.path('$.session')",
}
The problem: Above code doesn't work since $data is not valid JSON string. How one can convert the $data to valid JSON string? Could't find a $util to do that inside template mapper.
Thanks!

AWS API gateway response body template mapping (foreach)

I am trying to save data in S3 through firehose proxied by API gateway. I have create an API gateway endpoint that uses the AWS service integration type and PutRecord action for firehose. I have the mapping template as
{
"DeliveryStreamName": "test-stream",
"Records": [
#foreach($elem in $input.path('$.data'))
{
"Data": "$elem"
}
#if($foreach.hasNext),#end
#end
]
}
Now when I test the endpoint with below JSON
{
"data": [
{"ticker_symbol":"DemoAPIGTWY","sector":"FINANCIAL","change":-0.42,"price":50.43},{"ticker_symbol":"DemoAPIGTWY","sector":"FINANCIAL","change":-0.42,"price":50.43}
]
}
JSON gets modified and shows up as below after the transformation
{ticker_symbol=DemoAPIGTWY, sector=FINANCIAL, change=-0.42, price=50.43}
: is being converted to = which is not a valid JSON
Not sure if something is wrong in the above mapping template
The problem is, that $input.path() returns a json object and not a stringified version of the json. You can take a look at the documentation here.
The Data property expects the value to be a string and not a json object. So long story short - currently there is no built in function which can revert a json object into its stringified version. This means you need to re read the current element in the loop via $input.json(). This will return a json string representation of the element, which you then can add as Data.
Take a look at the answer here which illustrates this concept.
In your case, applying the concept described in the link above would result in a mapping like this:
{
"DeliveryStreamName": "test-stream",
"Records": [
#foreach($elem in $input.path('$.data'))
{
#set($json = $input.json("$[$foreach.index]"))
"Data":"$util.base64Encode($json)",
}
#if($foreach.hasNext),#end
#end
]
}
API Gateway considers the payload data as a text and not as a Json unless explicitly specified.
Kinesis also expects data to be in encoded format while proxying through API Gateway.
Try the following code and this should work, wondering why the for loop has been commented in the mapping template.
Assuming you are not looping through the record set, the following solution should work for you.
{
"DeliveryStreamName": "test-stream",
"Record": {
"Data": "$util.base64Encode($input.json('$.Data'))Cg=="
}
}
Thanks & Regards,
Srivignesh KN

WSO2DSS batch insert with JSON data

Using WSO2 DSS 3.5.1 I'd like to find a JSON format for inserting multiple records
having resource
<resource method="POST" path="/insert/count">
<call-query href="insert_rawdata">
<with-param name="timeslot" query-param="timeslot" />
<with-param name="cell_id" query-param="cell_id" />
</call-query>
</resource>
and query
<query id="insert_rawdata" useConfig="PG_DB">
<sql>INSERT INTO mobile_data ( date_time , timeslot , cell_id )
VALUES (
NOW()::timestamp, :timeslot::timestamp with time zone, :cell_id )
ON CONFLICT (timeslot, cell_id) DO NOTHING </sql>
<param name="timeslot" sqlType="STRING" type="IN"/>
<param name="cell_id" sqlType="INTEGER" type="IN"/>
</query>
it's pretty straightfoward to POST multiple records with XML
<test_list>
<data>
<timeslot>2017-11-13 14:00</timeslot>
<cell_id>1234</cell_id>
</data>
<data>
<timeslot>2017-11-13 14:00</timeslot>
<cell_id>1235</cell_id>
</data>
</test_list>
Reading the documentation https://docs.wso2.com/display/DSS351/Using+JSON+Messages+with+RESTful+Services looks useful, however seems the documentation is not right
according to the documentation the JSON object should be _post$RESOURCE, but it's _post_$RESOURCE
working POST request:
{
"_post_insert_count" : {
"timeslot": "2017-11-13 14:00",
"cell_id": 1234
}
}
however I am unable to find correct JSON syntax/format to POST (insert) multiple records with single request, according to the documentation should be
{ "_post_insert_count_batch_req": {
"_post_insert_count": [
{
"timeslot": "2017-11-13 14:00",
"cell_id": 1234
} ,
{
"timeslot": "2017-11-13 14:00",
"cell_id": 1235
}]
}
then I got an exception
java.lang.NullPointerException
at org.apache.axis2.json.gson.GsonXMLStreamReader.validateArgumentTypes(GsonXMLStreamReader.java:783)
at org.apache.axis2.json.gson.GsonXMLStreamReader.nextValue(GsonXMLStreamReader.java:734)
at org.apache.axis2.json.gson.GsonXMLStreamReader.readValue(GsonXMLStreamReader.java:626)
so - someone could help to build a valid JSON request for inserting multiple records?
Thanks for any hint
working example:
{
"_post_insert_items_batch_req": {
"_post_insert_items": [{
"timestamp": "2017-11-13 14:00:00",
"school": "Regina Pace",
"eventid": 1234
},
{
"timestamp": "2017-11-13 14:00:00",
"school": "Regina Pace",
"evenid": 1235
}
]
}
}
which is strange as last time I had NPE from similar request, so I don't really understand where's the problem

WSO2DSS 3.5.1 - Issue in JSON response from a RESTful service

I have defined a restful service with nested queries. Output mapping is defined in XML. I get proper response as XML. But if I request a JSON response using Accept:Application/json I get
{
"Fault": {
"faultcode": "soapenv:Server",
"faultstring": "Error while writing to the output stream using JsonWriter",
"detail": ""
}
}
I was getting below exception in 3.5.0 and I found a jira saying it is fixed in 3.5.1. So I tried in 3.5.1 now I am not getting below exception but the same output.
javax.xml.stream.XMLStreamException: Invalid Staring element
Please note I have also tried the escapeNonPrintableChar="true" option in my queries but no use. Strange thing is it working for different data sets. Just one particular data set is throwing this output.
I have changed the JSON formatters as below and got it to work but there is a problem in that.
<messageFormatter contentType="application/json" class="org.apache.axis2.json.JSONMessageFormatter"/>
<!--messageFormatter contentType="application/json" class="org.apache.axis2.json.gson.JsonFormatter" / -->
<messageBuilder contentType="application/json" class="org.apache.axis2.json.JSONOMBuilder"/>
<!--messageBuilder contentType="application/json" class="org.apache.axis2.json.gson.JsonBuilder" /-->
If I use above formatter the null values are not represented properly. Like I get
"Person": {
"Name": {
"#nil": "true"
}
but I want it as (like the other JSON formatter used to give)
"Person": {
"Name": null
}
Any help please. Is there a bug still left in this area?
When you are creating the query in your output response, you define the format you want to receive the response you can select xml or json, in the case you mention you can select the json option, then select generate response this creates this json structure.
{
"entries": {
"entry": [
{
"field1": "$column1",
"field2": "$column2"
}
]
}
}
Then you can modify the answer you need with your fields. Here is an example of how I use it in my query
{
"Pharmacies": {
"Pharmacy": [
{
"ID": "$Id",
"Descripcion": "$Desc",
"Latitude": "$Latitude",
"Longitude": "$Longitude",
"Image": "$Image"
}
]
}
}
The values ​​with "$" are correspond to the name of the column of the query
Regards