0

* Edited with new, complete, JSON data *

I am going to apologize in advance as I'm a total coding neophyte. The manager who decided to try a project.

I was hoping someone could help me with a code snippet to parse the following ugly JSON result. It's the result of the API call and contains 4 "records". I had to paste it in as a snippet due to the formatting, my apologies.

{"url":"http://www.msasnow.org/trail-reports/pere-marquette-snowmobile-club/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/pere-marquette-snowmobile-club/","resourceId":"29ce67ff3db8907d01f84ad45b6b47e4","data":[{"group":[{"trailName":[{"text":"Pere Marquette Snowmobile Club Trail Report"}],"trailCondition":[{"text":"Fair"}],"reportDate":[{"text":"January 10th, 2017 @ 11:20am"}]}]}]},"pageData":{"resourceId":"29ce67ff3db8907d01f84ad45b6b47e4","statusCode":200,"timestamp":1484190106983},"timestamp":1484190107253,"sequenceNumber":0}}
{"url":"http://www.msasnow.org/trail-reports/greater-grayling-snowmobile-assoc/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/greater-grayling-snowmobile-assoc/","resourceId":"660750825d7a7e665acfd3a94ac3d20e","data":[{"group":[{"trailName":[{"text":"Greater Grayling Snowmobile Assoc. Trail Report"}],"trailCondition":[{"text":"Good"}],"reportDate":[{"text":"January 09th, 2017 @ 10:50am"}]}]}]},"pageData":{"resourceId":"660750825d7a7e665acfd3a94ac3d20e","statusCode":200,"timestamp":1484190108241},"timestamp":1484190108467,"sequenceNumber":1}}
{"url":"http://www.msasnow.org/trail-reports/st-helen-snowmobile-club/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/st-helen-snowmobile-club/","resourceId":"63ba9e57962c0103cf401021656d5231","data":[{"group":[{"trailName":[{"text":"St. Helen SnowPackers Snowmobile Club Trail Report"}],"trailCondition":[{"text":"Poor"}],"reportDate":[{"text":"January 09th, 2017 @ 5:02pm"}]}]}]},"pageData":{"resourceId":"63ba9e57962c0103cf401021656d5231","statusCode":200,"timestamp":1484190108869},"timestamp":1484190109341,"sequenceNumber":2}}
{"url":"http://www.msasnow.org/trail-reports/cadillac-winter-promotions/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/cadillac-winter-promotions/","resourceId":"d977860e12e8d285d5e7ea21e17bf43e","data":[{"group":[{"trailName":[{"text":"Cadillac Winter Promotions Trail Report"}],"trailCondition":[{"text":"Good"}],"reportDate":[{"text":"January 10th, 2017 @ 3:25pm"}]}]}]},"pageData":{"resourceId":"d977860e12e8d285d5e7ea21e17bf43e","statusCode":200,"timestamp":1484190110156},"timestamp":1484190110365,"sequenceNumber":3}}

I'm trying to extract the trailName, trailCondition, and reportDate values from each record so I can write them out in a web page (i've got that part down). But as the "values" are in a lower node on the tree, and there are multiple records I'm at a loss.

The JSON is created by import.io and I don't have the ability to modify it at all.

I was attempting javascript but am open to all options...geared to a coding neophyte.

Thanks for your valuable time, and mercy... Marc

  • use JSON.parse to parse a JSON string – Jaromanda X Jan 12 '17 at 05:58
  • You might want to use something like http://jsonprettyprint.com so you can see the structure of your JSON (which is not, incidentally, 'an array'). After parsing it, you can use standard js notation to extract the bits you need – pvg Jan 12 '17 at 06:01

1 Answers1

1

The job isn't trivial as the format seems granular and uses objects and arrays for things that likely can be key:value pairs. A general solution will take a bit of effort.

Here's how to explicitly get at some of the data you seem to want which is inside the group array. Maybe you can adapt it to what you want.

var data = JSON.parse('{"url":"http://www.msasnow.org/trail-reports/pere-marquette-snowmobile-club/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/pere-marquette-snowmobile-club/","resourceId":"bb56c59af972a87e62bcba4206a05d4d","data":[{"group":[{"Trail Name":[{"text":"Pere Marquette Snowmobile Club Trail Report"}],"Trail Condition":[{"text":"Fair"}],"Report Date":[{"text":"January 10th, 2017 @ 11:20am"}]}]}]},"pageData":{"resourceId":"bb56c59af972a87e62bcba4206a05d4d","statusCode":200,"timestamp":1484143736420},"timestamp":1484143957298,"sequenceNumber":0}}');

// Get the group, which is an array
var group = data.result.extractorData.data[0].group;

// Get data from the group
group.forEach(function(group) {
  Object.keys(group).forEach(function(key) {
   console.log(key + ': ' + group[key][0].text);
  });
});

Based on the edited OP, the following will process multiple records. The part to be careful of is that data is an array of group objects. Your examples only have one group so the code just gets data[0].group.

The format allows multiple group objects in each data array, so likely some clever person will make use of that in future (or perhaps not, but it's simple to guard against).

So you probably should loop over the data array and extract each group, even though there's currently only one. That means you'll also need to deal with returning say an array of result objets, not just a single object.

// Assuming data arrives as records separated by returns
var data = '{"url":"http://www.msasnow.org/trail-reports/pere-marquette-snowmobile-club/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/pere-marquette-snowmobile-club/","resourceId":"29ce67ff3db8907d01f84ad45b6b47e4","data":[{"group":[{"trailName":[{"text":"Pere Marquette Snowmobile Club Trail Report"}],"trailCondition":[{"text":"Fair"}],"reportDate":[{"text":"January 10th, 2017 @ 11:20am"}]}]}]},"pageData":{"resourceId":"29ce67ff3db8907d01f84ad45b6b47e4","statusCode":200,"timestamp":1484190106983},"timestamp":1484190107253,"sequenceNumber":0}}\n' +
           '{"url":"http://www.msasnow.org/trail-reports/greater-grayling-snowmobile-assoc/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/greater-grayling-snowmobile-assoc/","resourceId":"660750825d7a7e665acfd3a94ac3d20e","data":[{"group":[{"trailName":[{"text":"Greater Grayling Snowmobile Assoc. Trail Report"}],"trailCondition":[{"text":"Good"}],"reportDate":[{"text":"January 09th, 2017 @ 10:50am"}]}]}]},"pageData":{"resourceId":"660750825d7a7e665acfd3a94ac3d20e","statusCode":200,"timestamp":1484190108241},"timestamp":1484190108467,"sequenceNumber":1}}\n' +
           '{"url":"http://www.msasnow.org/trail-reports/st-helen-snowmobile-club/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/st-helen-snowmobile-club/","resourceId":"63ba9e57962c0103cf401021656d5231","data":[{"group":[{"trailName":[{"text":"St. Helen SnowPackers Snowmobile Club Trail Report"}],"trailCondition":[{"text":"Poor"}],"reportDate":[{"text":"January 09th, 2017 @ 5:02pm"}]}]}]},"pageData":{"resourceId":"63ba9e57962c0103cf401021656d5231","statusCode":200,"timestamp":1484190108869},"timestamp":1484190109341,"sequenceNumber":2}}\n' +
           '{"url":"http://www.msasnow.org/trail-reports/cadillac-winter-promotions/","result":{"extractorData":{"url":"http://www.msasnow.org/trail-reports/cadillac-winter-promotions/","resourceId":"d977860e12e8d285d5e7ea21e17bf43e","data":[{"group":[{"trailName":[{"text":"Cadillac Winter Promotions Trail Report"}],"trailCondition":[{"text":"Good"}],"reportDate":[{"text":"January 10th, 2017 @ 3:25pm"}]}]}]},"pageData":{"resourceId":"d977860e12e8d285d5e7ea21e17bf43e","statusCode":200,"timestamp":1484190110156},"timestamp":1484190110365,"sequenceNumber":3}}';

// Function to process each record and return an object like:
// {trailName: value,
//  trailCondition: value,
//  reportDate: value}
function processRecord(record) {
  record = JSON.parse(record);
  var group = record.result.extractorData.data[0].group;
  var result = {}
  group.forEach(function(group) {
    Object.keys(group).forEach(function(key) {
      result[key] = group[key][0].text;
    });
  });
  return result;
}
              
// Split the data into records on new lines,
// Process each record and return result objects in an array
var processedData = data.split('\n').map(record => processRecord(record));


// Display results: for each record, write out each key and its value
processedData.forEach(function (record) {
  Object.keys(record).forEach(function(key) {
    console.log(key + ': ' + record[key]);
  })
});

// Which can also be written using arrow functions, but it's a bit obfuscated:
/*
processedData.forEach(record =>
  Object.keys(record).forEach(key =>
    console.log(key + ': ' + record[key])
  )
);
*/   

You could also format the result as a table, but I'll leave that up to you. ;-)

RobG
  • 142,382
  • 31
  • 172
  • 209
  • RobG - Thank you for that code, I was able to get it to work using the JSON I originally had in the post. I've updated it with the multi-record data and was wondering how difficult it would be to apply to multiple "records". I assume when I'm acutally calling it from the HTTP request it will be handled differently. Thanks again so much!! My son is finally getting interested in my little project. – Marc Lampcov Jan 12 '17 at 19:30
  • The data you posted isn't valid JSON, it should look like an array literal `'[{...record...},{...record...},{...record...}]'` rather than what you posted, which is `'{...record...}{...record...}{...record...}'`. The above can be refactored to a function that accepts a single record, then you can split the data into individual records and pass them one at a time to the function. – RobG Jan 12 '17 at 20:52