Search code examples
javascriptjsonfor-in-loop

formatting JSON to work with existing for/in loop Javascript


hopefully I can get some help with this issue. First, the below code works fine. The JSON is read in from a file that contains only this JSON, the For in Loop iterates through it and populates without issue.

{

"ID:1": {
  "employee": "Mike",
  "start": {
    "t": "2018-08-01",
    "v": 28
  },
  "end": {
    "t": "2018-08-14",
    "v": 39
  }
},
"ID:2": {
  "employee": "John",
  "start": {
    "t": "2018-08-01",
    "v": 43
  },
  "end": {
    "t": "2018-08-14",
    "v": 35
  }
},
}


function get_data(root,r_scale){

var my_data = [],
x=0;

for (r in root){
  start_t = root[r]['start'].t
  start_v = root[r]['start'].v
  end_t = root[r]['end'].t
  end_v = root[r]['end'].v
  change = Math.abs(start_v - end_v)
  my_data.push({
   change: change,
   id: x, 
   employee: root[r].employee, 
   start_t: start_t, 
   start_v: start_v,
   end_t: end_t,
   end_v: end_v
  })
  x = x + 1
  }

  return my_data

  };

Unfortunately, I need to put the JSON above into a larger blob that contains other JSON objects. So, I need to format it like this:

"employees": [

  {
    "ID": 1,
    "employee": "Mike",
    "start": {
      "t": "2018-08-01",
      "v": 28
    },
    "end": {
      "t": "2018-08-14",
      "v": 39
    }
  },


  {
    "ID": 2,
    "employee": "John",
    "start": {
      "t": "2018-08-01",
      "v": 43
    },
    "end": {
      "t": "2018-08-14",
      "v": 35
    }
  }

]

I cannot make this work. I can append ".employees" to root "root.employees[r]..." in the loop and see the data when I run a debugger. But each time I get "uncaught TypeError: Cannot read property 't' of undefined.

Thanks for any help!


Solution

  • I'm unsure why you get undefined errors, but your code can be simplified. You actually only map over the entries of your original data object, add a running index and the change property. This can be done as follows using Object.values (MDN):

    const data = {
    
    "ID:1": {
      "employee": "Mike",
      "start": {
        "t": "2018-08-01",
        "v": 28
      },
      "end": {
        "t": "2018-08-14",
        "v": 39
      }
    },
    "ID:2": {
      "employee": "John",
      "start": {
        "t": "2018-08-01",
        "v": 43
      },
      "end": {
        "t": "2018-08-14",
        "v": 35
      }
    },
    };
    
    const convert = (data) => {
      const employees = Object.values(data)
      .map(({ employee, start, end }, index) => ({ 
        id: index, 
        employee, 
        start, 
        end, 
        change: Math.abs(start.v - end.v) 
      }));
      return { employees };
    };
    
    
      console.log(convert(data))

    Note that you could also have directly gotten the entries of your original data usin the for-of loop. That way, you wouldn't have needed root[r] to access the entries using the keys.