Parsing complex JSON

We were building a UI control which gets data from JSON. To keep things simple, we wanted our users to specify JSON in a simple “.” manner e.g. if JSON looks like this

var obj = {
     name: 'Rafat Sarosh',
     address: 'Redmond. Seattle'

then the HTML can be as simple as this:

<my-control column='name' data='name'>;

and then in our directives we can parse the JSON by simply writing row[data] and get the data. Here row is referring to the JSON obj and ‘data’ is referring to ‘name’. Effectively, row[data] will translate to obj[name] in my directive. So far so good. This all works fine, till you get a simple JSON, and you are more or less certain of the shape of JSON. The user of my directive is happy to write a simple dot notation in his HTML to access the data. But imagine, if JSON is little complex. e.g.

var obj = {

      f1: "Angular",
      f2: { 
             "name": "Rafat", 
             "address": [{ city: 'Seattle'}, {zip: '98059' }] 
      f3: {
             "name": "Tim", 
             "address": [{ city: 'Redmond'}, {house: () => "I am function" }]
      f4: [1, 2, 3]

then it becomes little difficult to write a simple parsing function. Imagine the following test cases if user want to access the data as follows:

'f3.address[1].house')()  //Should return "I am function"

'f3.address[0].city' //Should return 'Redmond'

'' //Should return 'Rafat'

'f4[2]' //Should return 3

'f1' //Should return 'Angular'

So here is the code to parse JSON of any complexity.

function getValue(object: any, path: string, replace: boolean = true): T {

  //convert, all the .,[,] to * so I can break the strings on *
  if (replace) //A switch so I don't do this every time in my recursive loop
      path = path.replace(/\]\.|\.|\[|\]/g, "*");
  var index = path.indexOf('*');
  if (index === -1)
      return object[path];

  //Get the first segment
  var firstSegment= path.slice(0, index);
  var remainingSegments= path.slice(index + 1);

  if (object[firstSegment] !== undefined && remainingSegments.length > 0) {
       return getValue(object[firstSegment], remainingSegments, false);
  } else
       return object[firstSegment];

Happy Coding!!!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s