fb
WSO2 Enterprise Integrator 4 min

From XML to JSON, how to handle an array of one

Rob Blaauboer
Rob Blaauboer
Integration Consultant & WSO2 Trainer
12 jun no 1
Scroll

When one uses WSO2 Enterprise Service Bus (WSO2 ESB) in a REST way, for instance for passing calls of an AngularJS web application to multiple back end systems, sooner or later one will discover the generated JSON is not always formatted the same.

For instance, when one retrieves data passing in search criteria, the returned JSON will be formatted differently, depending on the number of entities returned. When multiple entries are returned, it will look like this

1
2
3
4
5
{ “entity” :
  [ { “attr1” : “value”, “attr2” : “another value”}, 
     { “attr1” : “value”, “attr2” : “another value”}
  ]
}

When one entity is returned, it will look like this:

1
2
3
{ “entity” : 
  { “attr1” : “value”, “attr2” : “another value”} 
}

Where one might expect:

1
2
3
4
{ “entity” :
  [ { “attr1” : “value”, “attr2” : “another value”}
  ]
}

The difference lies in the square brackets that are omitted in the middle example.

Attribute or array?

The underlying problem is there is no way to tell the difference between an attribute or an array with one entry in XML. Here it’s clear, there are two entity nodes, so they will be transformed into an array:

1
2
3
4
5
6
7
8
9
10
<response >
   <entity>
      <attr1>value</attr1>
      <attr2>another value</attr2>
   </entity>
   <entity>
      <attr1>value</attr1>
      <attr2>another value</attr2>
   </entity>
</response>

But what about this one? Is entity just an attribute like attr1 and attr2? Or is it an array with one entry?

1
2
3
4
5
6
<response >
   <entity>
      <attr1>value</attr1>
      <attr2>another value</attr2>
   </entity>
</response>

There is no way to tell the difference, is there? … Well in fact there is, by including an annotation. StAXON supports the processing instruction. By adding this processing instruction to the XML, StAXON knows it should create an array for this lonely element. Of course back end systems like the WSO2DSS will not include this for you, luckily one can always add it to the XML by using the XSLT mediator.

EXAMPLE TIME

Instead of setting up the whole typical chain, with WSO2DSS and a database, I will use the payload factory inside a custom proxy to show how you can tell the XML2JSON conversion library (StAXON) to return a single entity in an array, making your service more consequent:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?xml version="1.0" encoding="UTF-8"?>
<proxy http://ws.apache.org/ns/synapse">http://ws.apache.org/ns/synapse"
       name="jsonTest"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="full"/>
         <switch source="//show/text()">
            <case regex="two">
               <payloadFactory media-type="xml">
                  <format>
                     <response >
                        <entity>
                           <attr1>value</attr1>
                           <attr2>another value</attr2>
                        </entity>
                        <entity>
                           <attr1>value</attr1>
                           <attr2>another value</attr2>
                        </entity>
                     </response>
                  </format>
                  <args/>
               </payloadFactory>
            </case>
            <case regex="one">
               <payloadFactory media-type="xml">
                  <format>
                     <response >
                        <entity>
                           <attr1>value</attr1>
                           <attr2>another value</attr2>
                        </entity>
                     </response>
                  </format>
                  <args/>
               </payloadFactory>
            </case>
            <case regex="one-fixed">
               <payloadFactory media-type="xml">
                  <format>
                     <response ><?xml-multiple?><entity>
                           <attr1>value</attr1>
                           <attr2>another value</attr2>
                        </entity>
                     </response>
                  </format>
                  <args/>
               </payloadFactory>
            </case>
            <default>
               <log level="full"/>
               <respond/>
            </default>
         </switch>
         <log level="full"/>
         <respond/>
      </inSequence>
   </target>
   <description/>
</proxy>

WSO2 DSS jsonTEST

Figure 1 Overview in WSO2 Development studio of the jsonTest custom proxy

Now it’s time to call this custom proxy service a few times. We have installed the ESB on localhost and deployed the service (jsonTest) to it. Now we use curl to test:

1
curl -H "Content-Type: application/json" -X POST -d '{ "show" : "two"}' http://localhost:8280/services/jsonTest

Returns: {“response”:{“entity”:[{“attr1″:”value”,”attr2″:”another value”},{“attr1″:”value”,”attr2″:”another value”}]}}

It returns an array of entity objects.

1
curl -H "Content-Type: application/json" -X POST -d '{ "show" : "one"}' http://localhost:8280/services/jsonTest

Returns: {“response”:{“entity”:{“attr1″:”value”,”attr2″:”another value”}}}

The returned entity is modeled like a single attribute, not as an array with just one entry.

1
curl -H "Content-Type: application/json" -X POST -d '{ "show" : "one-fixed"}' http://localhost:8280/services/jsonTest

Returns: {“response”:{“entity”:[{“attr1″:”value”,”attr2″:”another value”}]}}

Now it returns an array with only one entity object.

Try it yourself!

If you want to try it yourself you can do it in some simple steps:

  1. install WSO2 ESB;
  2. install WSO2 Dev Studio;
  3. create an ESB config project;
  4. create a custom proxy;
  5. copy the example above in the source view of the custom proxy;
  6. save the custom proxy;
  7. create a CAR file;
  8. deploy it on a server;
  9. test it with curl.

Full API lifecycle Management Selection Guide

WHITEPAPER

smartmockups l0qqucke