Thursday, March 27, 2014

Parsing JSON strings in MVEL interactive shell

This is a pretty niche application - so I will get started without any introduction. Assumption here is that if you reach here, you are probably looking for this exact same thing in google or some other search engine. 

I wanted to parse the following JSON string in MVEL interactive shell:
{"f":{"v":{"dd":"Windows-7~D~windows","tz":0,"br":"c~33.0.1750.154"},"p":{"cp":"http://247-demo.net/"}},"bsid":"6fb4363f-5e06-4f10-b1ba-463a1f5e961f-1","it":0,"vi":"6fb4363f-5e06- 4f10-b1ba-463a1f5e961f","tseq":1,"tp":"1","vg":"4","vt":"1.3","as":"1","idm":{"lkp":"email","lkv":"myemail@email.com"},"vp":"6.0","ec":"10022","ti":"t1","up":1395809903783,"v":"default","tnt":"DEMO_C2C","rt":30.753,"vc":"v0.1","st":1395809906804,"rv":69.864,"bd":"Mozilla%2F5.0%20(Windows%20NT%206.1%3B%20WOW64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F33.0.1750.154%20Safari%2F537.36"}
I wanted to use the excellent Gson library from google. Here is a link to the JavaDoc for the library. Of course, you can also use any other JSON parser library of your choice. I wanted an easy way to get to a value in a nested JSON string as shown above, e.g., "f.v.br", and the JsonParser class in the Gson library is a great choice for that.

First, in order to use Gson interactively from MVEL shell, we have to load both jars. As most of us MVEL users are aware, MVEL is notoriously poor on documentation - you have to scramble to do anything. Anyways, rants aside, here is how to load two jars and get the MVEL prompt:
$ java -cp "gson-2.2.2.jar;mvel2-2.1.3.Final.jar" org.mvel2.sh.Main

MVEL-Shell (MVELSH)
Copyright (C) 2010, Christopher Brock, The Codehaus
Version 2.1.0

Starting session...
No config file found.  Loading default config.
[01:28PM] mvel2$ import com.google.gson.JsonParser;
class com.google.gson.JsonParser
This, of course, assumes that both the jars are located in the same folder from where the above command is executed. Once you are at the shell, it is reasonably straightforward. We will have to use JsonParser to parse the JSON string in a JsonObject, and then use get() calls to reach to the value. Here is the demo session. The output from the shell is in grey.
[01:29PM] mvel2$ a='{ "f": { "v": { "dd": "Windows-7~D~windows", "tz": 0, "br": "c~33.0.1750.154" }, "p": { "cp": "http://247-demo.net/" } }, "bsid": "6fb4363f-5e06-4f10-b1ba-463a1f5e961f-1", "it": 0, "vi": "6fb4363f-5e06- 4f10-b1ba-463a1f5e961f", "tseq": 1, "tp": "1", "vg": "4", "vt": "1.3", "as": "1", "idm": { "lkp": "email", "lkv": "myemail@email.com" }, "vp": "6.0", "ec": "10022", "ti": "t1", "up": 1395809903783, "v": "default", "tnt": "DEMO_C2C", "rt": 30.753, "vc": "v0.1", "st": 1395809906804, "rv": 69.864, "bd": "Mozilla%2F5.0%20(Windows%20NT%206.1%3B%20WOW64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F33.0.1750.154%20Safari%2F537.36" }'
{ "f": { "v": { "dd": "Windows-7~D~windows", "tz": 0, "br": "c~33.0.1750.154" }, "p": { "cp": "http://247-demo.net/" } }, "bsid": "6fb4363f-5e06-4f10-b1ba-463a1f5e961f-1", "it": 0, "vi": "6fb4363f-5e06- 4f10-b1ba-463a1f5e961f", "tseq": 1, "tp": "1", "vg": "4", "vt": "1.3", "as": "1", "idm": { "lkp": "email", "lkv": "myemail@email.com" }, "vp": "6.0", "ec": "10022", "ti": "t1", "up": 1395809903783, "v": "default", "tnt": "DEMO_C2C", "rt": 30.753, "vc": "v0.1", "st": 1395809906804, "rv": 69.864, "bd": "Mozilla%2F5.0%20(Windows%20NT%206.1%3B%20WOW64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F33.0.1750.154%20Safari%2F537.36" }
[01:40PM] mvel2$ p = new JsonParser();
com.google.gson.JsonParser@133e8c9
[01:40PM] mvel2$ e = p.parse(a);
{"f":{"v":{"dd":"Windows-7~D~windows","tz":0,"br":"c~33.0.1750.154"},"p":{"cp":"http://247-demo.net/"}},"bsid":"6fb4363f-5e06-4f10-b1ba-463a1f5e961f-1","it":0,"vi":"6fb4363f-5e06- 4f10-b1ba-463a1f5e961f","tseq":1,"tp":"1","vg":"4","vt":"1.3","as":"1","idm":{"lkp":"email","lkv":"myemail@email.com"},"vp":"6.0","ec":"10022","ti":"t1","up":1395809903783,"v":"default","tnt":"DEMO_C2C","rt":30.753,"vc":"v0.1","st":1395809906804,"rv":69.864,"bd":"Mozilla%2F5.0%20(Windows%20NT%206.1%3B%20WOW64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F33.0.1750.154%20Safari%2F537.36"}
[01:47PM] mvel2$ e.getClass()
class com.google.gson.JsonObject
[01:49PM] mvel2$ e.get("f").get("v").get("br")
"c~33.0.1750.154"
That is pretty much it - parsing a nested JSON string using MVEL shell.