2

I'm using Mule 3.4 CE and I have a JSON data coming through HTTP in the following format:

{
   "People" : [
    {
       "Details" : 
       {
         "Name" : "John Smith",
         "Email" : "abc@mail.com"
       }
    },
    {
       "Details" : 
       {
         "Name" : "Tim Smith",
         "Email" : "def@mail.com"
       }
    },
    {
       "Details" : 
       {
         "Name" : "Ken Smith",
         "Email" : "ghi@mail.com"
       }
    },
}

I need to extract the emails and lookup the Salesforce contact with these emails and at the same time I want to retain the JSON payload. So my question is how do I extract the emails through MEL? (for e.g. something like "People/Details/*/Email" - I know this is not a valid, but I'm looking for the right syntax.

Edit: I want to extract the emails in one shot rather than indexing (for e.g. People/Details[0].Email, possibly using MEL.

Tech Matrix
  • 283
  • 2
  • 7
  • 13

2 Answers2

14

There best way to query json is to transform it to a Map.

<json:json-to-object-transformer returnClass="java.util.HashMap" />

And then query it using MEL like standard MVEL or Java syntax

<logger message="#[payload.People[0].Details.email]" level="INFO" />

If you want to keep the original json payload intact, you can store the map in a variable using an enricher:

<enricher target="#[flowVars.myJsonMap]">
   <json:json-to-object-transformer returnClass="java.util.HashMap" />
</enricher>

And query the variable instead of the payload:

<logger message="#[flowVars.myJsonMap.People[0].Details.email]" level="INFO" />

You could also map the json to a custom class using Jackson and change the returnClass attribute to your class.

This MEL cheat sheet detail JSON processing with MEL and also how to handle Maps, arrays etc: http://www.mulesoft.org/documentation/display/current/MEL+Cheat+Sheet

Note: You may come across a #[json:] evaluator, but this is deprecated in favour of the approach above.

UPDATE:

If you want to grab all the emails at once you can use MVEL projections:

<enricher target="#[flowVars.myJsonMap]" source="#[(Details.email in payload.People)]">
       <json:json-to-object-transformer returnClass="java.util.HashMap" />

    </enricher>

Mvel projections: http://mvel.codehaus.org/MVEL+2.0+Projections+and+Folds

Ryan Carter
  • 11,441
  • 2
  • 20
  • 27
  • 2
    You can also use a simple Groovy one-liner to parse the map to a list of emails: #[groovy:flowVars.myJsonMap.People.collect() { it.Details.Email }] – Anton Kupias Feb 05 '14 at 22:59
  • @Ryan - Thanks for your reply. I'm looking to extract all the emails in, possibly, one activity. I can write a java component and do it, but I was wondering if it can be done via MEL. – Tech Matrix Feb 05 '14 at 23:01
  • @Anton - Thanks for your comment. I'll try your example and see if that will fit my needs. – Tech Matrix Feb 05 '14 at 23:02
  • You may also want to consider using a flow-ref inside the enricher , and a sub-flow for the json transformer and a set-payload with the Groovy method, so you will have just the email list in your flowVar. – Anton Kupias Feb 05 '14 at 23:08
  • The groovy evaluator is also deprecated in favor of plain MEL. If you want to extract all the emails in on go you can use MVEL folds: flowVars.emails = (email in payload.People). Updated my answer to show full example. – Ryan Carter Feb 05 '14 at 23:16
  • Also updated the expression ton include 'Details' as I was missing that object and added a link to Mvel folds. – Ryan Carter Feb 05 '14 at 23:33
  • @Ryan - This is what exactly I was looking for and it worked as you said. Thanks for your answer. – Tech Matrix Feb 06 '14 at 00:01
0

If you want to get the particular email in the details use the below MEL expression.

#[json:People[0]/Details/Email]

If you want to get all the emails, pass the json path of repeatable in ForEach Collections then pass the path to get Email as shown below.

 <flow name="parsingjsonFlow">
    <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
    <foreach collection="#[json:People]" doc:name="For Each">
        <logger message="#[json:/Details/Email]" level="INFO" doc:name="Logger"/>
    </foreach>
    <catch-exception-strategy doc:name="Catch Exception Strategy">
        <logger message="#[exception.getClass()]" level="INFO" doc:name="Logger"/>
    </catch-exception-strategy>
</flow>