Accessing JSON array dynamically using json-eval in WSO2 MI

Isuru Liyanage
CodeBlog
Published in
3 min readMay 12, 2023

When doing integration we all face a requirement to access a JSON array dynamically in WSO2 Micro Integrator. Most of us use a custom class mediator or a script mediator to achieve this.
In this blog I’m going to show you how to access JSON array dynamically using Out of the box items without implementing custom code.

So we have a below JSON payload coming from the back-end and we need to access the items inside the array dynamically.

{
"Basket":[
{
"box":[
{
"Name":"Milk"
}
]
},
{
"box":[
{
"Name":"Cheese"
}
]
}
]
}

In my use-case client is sending the index value of the array that he/she need to access from the JSON array payload which comes from the back-end.
To achieve this first we need to have two property mediators that fetch the client value from the incoming JSON request. I have created two property mediators with the name “Basket” to fetch index value of the Basket array and the “box” property mediator to fetch the index value of the nest array inside Basket array.

<property expression="json-eval($.Basket)" name="Basket" scope="default" type="STRING"/>
<property expression="json-eval($.box)" name="box" scope="default" type="STRING"/>

From json-eval($.Basket) and json-eval($.box) we will be getting the values from the below payload that comes in to the WSO2 Micro Integrator.

{
"Basket": 1,
"box": 0
}

Now we have the index values of the array, next step is to create the json-eval expression which works dynamically to above income request.
To achieve the requirement I’ll be using a property mediator to build the json-eval expression

<property expression="fn:concat('json-eval($.Basket[', $ctx:Basket, '].box[', $ctx:box, '].Name)')" name="jsonPath" scope="default" type="STRING"/>

In here I have used the concat operation to prevent the JSON path compilation failure at run time. The $ctx:Basket and $ctx:box will fetch the dynamic values that are stored.
If we use a log mediator and log the “jsonPath” property mediator we can see the expression that we build as below

Now we can use the built expression which stored in the “jsonPath” property mediator as below to access the array and get the value

<property expression="json-eval({$ctx:jsonPath})" name="content"/>

If we log above content property mediator you can see the array value as below

As you can see the expression is json-eval($.Basket[1].box[0].Name) according to the JSON payload the value will be Cheese.

Below is the full proxy service that I used for this

<?xml version="1.0" encoding="UTF-8"?>
<proxy name="arraytest" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<property expression="json-eval($.Basket)" name="Basket" scope="default" type="STRING"/>
<property expression="json-eval($.box)" name="box" scope="default" type="STRING"/>
<call>
<endpoint>
<address uri="http://run.mocky.io/v3/1131776a-fbec-4b86-ac7d-bff1396a2734">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
</call>
<property expression="fn:concat('json-eval($.Basket[', $ctx:Basket, '].box[', $ctx:box, '].Name)')" name="jsonPath" scope="default" type="STRING"/>
<log level="custom">
<property expression="$ctx:jsonPath" name="expression"/>
</log>
<log level="custom">
<property expression="json-eval({$ctx:jsonPath})" name="content"/>
</log>
<payloadFactory media-type="json">
<format>{"Basket item value" : "$1"}</format>
<args>
<arg evaluator="json" expression="{$ctx:jsonPath}"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
</proxy>

Hope you like this and Happy Coding !! :3

--

--