0

I'm trying to extract some of the fields from a Json response and push them into a Javascript array. I want the selection of the fields to be configurable. Here is what I'm doing:

Consider this as my JSON string:

{
    "id" : "1234",
    "orderNumber" : "1196",
    "createdOn" : "2019-07-02T12:03:39.697Z",
    "modifiedOn" : "2019-07-02T12:25:52.126Z",
    "testmode" : false,
    "customerEmail" : "a@b.com",
    "billingAddress" : {
      "firstName" : "John",
      "lastName" : "Doe",
      "address1" : "Wall Street",
      "address2" : null,
      "city" : "NYC",
      "state" : "NY",
      "countryCode" : "US",
      "postalCode" : "12345",
      "phone" : "1122334455"
    }
}

Say I want to extract some of the fields (defined in the FIELDS variable) and push them in an array.

# NOTE: the variable `data` here is my json object 

var FIELDS = ['id', 'orderNumber', 'customerEmail', 'billingAddress.firstName', 'billingAddress.lastName']

var lineItem = []

# parse the data (my Json object)
for (var i = 0; i < FIELDS.length; i++){
  lineItem.push(data[FIELDS[i]])
}

So, this seems to be working OK for the first level (the id, orderNumber and customerEmail) but not for the billingAddress.firstname, etc. This is what I'm wondering about.

My intent is to be able to modify the definition in the FIELDS variable without needing to make any change to the logic in the code.

Hope this makes sense. Thanks!

pascal
  • 641
  • 4
  • 12

2 Answers2

1

As long as there are no periods in the key names this will work.

var data = {
    "id" : "1234",
    "orderNumber" : "1196",
    "createdOn" : "2019-07-02T12:03:39.697Z",
    "modifiedOn" : "2019-07-02T12:25:52.126Z",
    "testmode" : false,
    "customerEmail" : "a@b.com",
    "billingAddress" : {
      "firstName" : "John",
      "lastName" : "Doe",
      "address1" : "Wall Street",
      "address2" : null,
      "city" : "NYC",
      "state" : "NY",
      "countryCode" : "US",
      "postalCode" : "12345",
      "phone" : "1122334455"
    }
};

var FIELDS = ['id', 'orderNumber', 'customerEmail', 'billingAddress.firstName', 'billingAddress.lastName'];

var lineItem = [];
for (var i = 0; i < FIELDS.length; i++){
  let obj = data;
  let parts = FIELDS[i].split(".");
  while(parts.length) obj = obj[parts.shift()];
  lineItem.push(obj)
}

console.log(lineItem);
I wrestled a bear once.
  • 22,983
  • 19
  • 69
  • 116
1

You just need a function that will split that path on . and traverse the JSON data. With that you can just map() over your fields.

let data = {"id" : "1234","orderNumber" : "1196","createdOn" : "2019-07-02T12:03:39.697Z","modifiedOn" : "2019-07-02T12:25:52.126Z","testmode" : false,"customerEmail" : "a@b.com","billingAddress" : {"firstName" : "John","lastName" : "Doe","address1" : "Wall Street","address2" : null,"city" : "NYC","state" : "NY","countryCode" : "US","postalCode" : "12345","phone" : "1122334455"}}
var FIELDS = ['id', 'orderNumber', 'customerEmail', 'billingAddress.firstName', 'billingAddress.lastName']

// split an traverse
const getFromPath = (path, data) => path.split('.')
      .reduce((curr, p) => curr && curr[p], data) // check for curr incase path is undefined
      
console.log(FIELDS.map(p => getFromPath(p, data)))

The function getFromPath will return undefined if any part of the traversal is not found in the object.

Mark
  • 90,562
  • 7
  • 108
  • 148