Sunday, February 9, 2014

XML to JSON conversion when multiple attributes and elements exists

There are situations that we need to convert xml payloads into JSON. WSO2 ESB provides this support and refer http://docs.wso2.org/display/ESB481/JSON+Support for more details.

To convert an XML payload into JSON, we have to set the messageType property to application/json in synapse configuration.

Here I discuss about XML to JSON conversion when multiple attributes and elements available in the payload.
You may receive a soap request as follows:

SOAP Request:
 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m0="http://services.samples" xmlns:xsd="http://services.samples/xsd">  
 <soapenv:Header/>  
 <soapenv:Body>  
 <m0:getQuote xmlns:m0="http://services.samples" id="12345">  
 <person sex="female" fn:target="urn:getQuote" xmlns:fn="abcdef" id="12345">  
 <firstname>Anna</firstname>  
 <lastname id="12345678">Smith</lastname>  
 </person>  
 <m0:request>  
 <m0:symbol>A</m0:symbol>  
 </m0:request>  
 </m0:getQuote>  
 </soapenv:Body>  
 </soapenv:Envelope>   

Person element contains multiple attributes sex, target, namespace and id.
i.e:  <person sex="female" fn:target="urn:getQuote" xmlns:fn="abcdef" id="12345">  

Also, lastnname is a sub element of person and it contains attribute as id and text content as "Smith"
i.e: <lastname id="12345678">Smith</lastname>

We will see how to covert such payload into json and its how the response looks like.

In ESB create a proxy service with SimpleStockQuote endpoint.

Proxy Service Configuration:
 <?xml version="1.0" encoding="UTF-8"?>  
 <proxy xmlns="http://ws.apache.org/ns/synapse"  
 name="XMLtoJSON"  
 transports="https,http"  
 statistics="disable"  
 trace="disable"  
 startOnLoad="true">  
 <target>  
 <inSequence>  
 <property name="messageType" value="application/json" scope="axis2"/>  
 <log level="full"/>  
 <respond/>  
 </inSequence>  
 <outSequence>  
 <send/>  
 </outSequence>  
 <endpoint>  
 <address uri="http://localhost:9000/services/SimpleStockQuoteService/"/>  
 </endpoint>  
 </target>  
 <description/>  
 </proxy>   


Note: 
For conversion, use "<property name="messageType" value="application/json" scope="axis2"/>" in the configuration as discussed above.

1. You have to start sample backend to receove response which is provided with WSO2 ESB. (Start axis2Service @ESB_HOME/samples/axis2Server)
2. Built SimpleStockQuote Service @ESB_HOME/samples/axis2Server/src/SimpleStockQuoteService by running "ant" command.
3. Send the SOAP request to proxy service using SOAP UI.


Response should be as follows:

 HTTP/1.1 200 OK  
 Host: shashi-ThinkPad-T530:8280  
 SOAPAction: "urn:getQuote"  
 Accept-Encoding: gzip,deflate  
 Content-Type: application/json  
 Date: Fri, 24 Jan 2014 06:00:54 GMT  
 Server: WSO2-PassThrough-HTTP  
 Transfer-Encoding: chunked  
 Connection: Keep-Alive  
 {"getQuote":{"@id":"12345","person":{"@id":"12345","@sex":"female","@target":"urn:getQuote","firstname":"Anna","lastname":{"@id":"12345678","$":"Smith"}},"request":{"symbol":"A"}}}  


Points to focus in response:

1. Content-Type should be 'application/json'
2. XML: 
<person sex="female" fn:target="urn:getQuote" xmlns:fn="abcdef" id="12345">  

JSON:
"person":{"@id":"12345","@sex":"female","@target":"urn:getQuote"

*** Attributes displayed with prefix '@' in JSON conversion. ("@id":"12345")
When nodes has text content as well as attributes, that text content is stored in a key with “$”

XML:
 <lastname id="12345678">Smith</lastname>  

JSON:
"lastname":{"@id":"12345678","$":"Smith"}

If a node has multiple children with the same tag name, they are converted into a numerically indexed array e.g. “person”
XML
 <person>Anvar</person>  
 <person>Porter</person>  
 <person>Raj</person>  

JSON
"person":["Anvar","Porter","Raj"]


SOAP request:
 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m0="http://services.samples" xmlns:xsd="http://services.samples/xsd">  
 <soapenv:Header/>  
 <soapenv:Body>  
 <m0:getQuote xmlns:m0="http://services.samples" id="12345">  
 <person>Anvar</person>  
 <person>Porter</person>  
 <person>Raj</person>  
 <m0:request>  
 <m0:symbol>A</m0:symbol>  
 </m0:request>  
 </m0:getQuote>  
 </soapenv:Body>  
 </soapenv:Envelope>  


Response:
 HTTP/1.1 200 OK  
 Host: shashi-ThinkPad-T530:8280  
 SOAPAction: "urn:mediate"  
 Accept-Encoding: gzip,deflate  
 Content-Type: application/json  
 Date: Sun, 09 Feb 2014 02:49:07 GMT  
 Server: WSO2-PassThrough-HTTP  
 Transfer-Encoding: chunked  
 Connection: Keep-Alive  
 {"getQuote":{"@id":"12345","person":["Anvar","Porter","Raj"],"request":{"symbol":"A"}}}  

1 comment:

  1. Shashi,

    Thanks for putting this together. We are still on ESB 4.7.0. Will this work with 4.7 or only with 4.8? I noticed "respond" is NOT available in 4.7.0. I just need a simple example showing my how to convert rows of data from a DB represented as XML into JSON, then send on to a json rest service for consumption.

    ReplyDelete