-1

I have an object in this format:

 var request =  {
      "student": [
        [
          "name",
          "age"
        ],
        [
          "Tom",
          12
        ],
        [
          "Jack",
          13
        ]
      ]
    };

I want to transform it into this:

 var request =  {
      "student": [
        {
          "name": "Tom",
          "age": 12
        },
        {
          "name": "Jack",
          "age": 13
        }
      ]
    }

I tried doing it this way:

var response = [];  
var keysCount = req.result[0].length; 
var responseCount = req.result.length - 1; 
var i = 0,
    j = 0,
    key;

for (j = 0; j < responseCount; j++) {
    for (i = 0; i < keysCount; i++) {
        key = req.result[0][i];
        response[j][key] = req.result[j + 1][i];
    }
} 
return response;

But, it is not working as expected.

Prerna Jain
  • 1,240
  • 2
  • 16
  • 34
  • 5
    That's not a "JSON object." JSON is a *textual notation* for data exchange. If you're dealing with JavaScript source code, and not dealing with a *string*, you're not dealing with JSON. You may have *recieved* it as JSON, but by the time you've parsed it and are manipulating it as above, JSON is completely irrelevant. – T.J. Crowder Jun 27 '16 at 05:11
  • Thanks for correcting @T.J.Crowder . – Prerna Jain Jun 27 '16 at 05:17
  • this look like an object. – Fiido93 Jun 27 '16 at 05:19
  • https://jsfiddle.net/xuczvx1n/ – dgk Jun 27 '16 at 05:25
  • Just out of curiosity, could you tell me from what book, tutorial, or web page you learned to call JavaScript objects "JSON"? I'm interested in tracking down the source of this annoying and widespread misconception. –  Jun 27 '16 at 05:29
  • @torazaburo: You and me, T, we'll hold back the tide! – T.J. Crowder Jun 27 '16 at 05:33
  • In what way does it not work as expected? Among other problems, you need to initialize `response[j]` to an empty object before you start adding properties to it. You could find the bugs in your logic quite easily by walking through it with a debugger. Do you know how to do that? –  Jun 27 '16 at 05:34
  • @T.J.Crowder Or, we could just throw in the towel. –  Jun 27 '16 at 05:47
  • 1
    @T.J.Crowder You might want to take a look at [this question](http://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation). – Spencer Wieczorek Jun 27 '16 at 06:49
  • @SpencerWieczorek: You mean so I can refer to it when this comes up? Felix and I are on the same page on this. (That said, I may add some minor edits to his excellent answer...) – T.J. Crowder Jun 27 '16 at 06:57
  • 1
    @T.J.Crowder *"You mean so I can refer to it when this comes up?"*, Yes. – Spencer Wieczorek Jun 27 '16 at 06:59
  • @SpencerWieczorek: I will indeed add it to my automated "That's not JSON" comment. :-) – T.J. Crowder Jun 27 '16 at 07:04

6 Answers6

6

It's a matter of looping through the first array and creating an array of objects for all the remaining arrays, using values at matching indexes to create properties on object:

var request = {
  "student": [
    [
      "name",
      "age"
    ],
    [
      "Tom",
      12
    ],
    [
      "Jack",
      13
    ]
  ]
};
// Get the header array
var headers = request.student[0];
// Create the new array but mapping the other entries...
var newArray = request.student.slice(1).map(function(entry) {
  // Create an object
  var newEntry = {};
  
  // Fill it in with the values at matching indexes
  headers.forEach(function(name, index) {
    newEntry[name] = entry[index];
  });
  
  // Return the new object
  return newEntry;
});
console.log(newArray);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
3

I would make a small function tabularize that takes an array of data where the first element is an array of headers, and the remaining elements are the rows

Code that follows uses ES6. If you need ES5 support, you can safely transpile this code using a tool like babel.

// your original data   
var request = {
  "student": [
    [
      "name",
      "age"
    ],
    [
      "Tom",
      12
    ],
    [
      "Jack",
      13
    ]
  ]
};

// tabularize function
var tabularize = ([headers, ...rows])=>
  rows.map(row=>
    headers.reduce((acc,h,i)=>
      Object.assign(acc, {[h]: row[i]}), {}));

// your transformed object
var request2 = {student: tabularize(request.student)};

// log the output
console.log(request2);

//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}

Or you can create the request object with the intended shape by passing the tabular data directly into the tabularize function at the time of object creation

// tabularize function
var tabularize = ([headers, ...rows])=>
  rows.map(row=>
    headers.reduce((acc,h,i)=>
      Object.assign(acc, {[h]: row[i]}), {}));

// your request object
var request = {
  student: tabularize([
    [
      "name",
      "age"
    ],
    [
      "Tom",
      12
    ],
    [
      "Jack",
      13
    ]
  ])
};

// log the output
console.log(request);

//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • Thanks @torazaburo. I highly respect your opinion and value your feedback. – Mulan Jun 27 '16 at 05:45
  • However, according to a [recent discussion on meta](http://meta.stackoverflow.com/questions/326630/should-answers-include-support-requirements) it is apparently recommended to note in your answer that you are using ES6 features. –  Jun 27 '16 at 05:48
  • @torazaburo thanks for the link. I added a note at the top of the answer. – Mulan Jun 27 '16 at 05:56
2

Let's start off by writing a little function just to create an object from two arrays, one of keys and one of their values:

function makeObjectFromPairs(keys, values) {
  var object = {};

  for (var i = 0; i < keys.length; i++) {
    object[keys[i]] = values[i];
  }

  return object;
}

// makeObjectFromPairs(['a', 'b'], [1, 2]) === {a: 1, b: 2}

Now we can use the first element of the students array as the keys, and each of the remaining elements as the values.

var keys = students[0];
var result = [];

for (var i = 1; i < students.length; i++) {
  result.push(makeObjectFromPairs(keys, students[i]);
}

You could use Array#map etc. as an alternative for the loops, but perhaps this basic approach is more accessible.

Fixing your original code

Since you made a valiant effort to solve this yourself, let's review your code and see where you went wrong. The key point is that you are not initializing each element in your output to an empty object before starting to add key/value pairs to it.

for (j = 0; j < responseCount; j++) {

    // Here, you need to initialize the response element to an empty object.
    response[j] = {};
1

Another solution :

var request = {
    "student": [
        [
            "name",
            "age"
        ],
        [
            "Tom",
            12
        ],
        [
            "Jack",
            13
        ]
    ]
};

var response = {};
var students = [];
var responseCount = request.student.length - 1;
var j = 0,
    key;
for (j = 0; j < responseCount; j++) {
    var student = {};
    request.student[0].forEach(function(name, index) {
        student[name] = request.student[1 + j][index];
    });
    students.push(student)

}
response["students"] = students;

console.log(response); // {"students":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
sharif2008
  • 2,716
  • 3
  • 20
  • 34
  • Sure, but all you've done is replaced one of the OP's loops with a `forEach`, added the necessary initialization of `student` to an empty object, and switched from assigning the result array element to pushing it. –  Jun 27 '16 at 06:02
1

Lodash solution

var keys = _.head(request.student);
var valueGroups = _.flatten(_.zip(_.tail(request.student)));

var studentObjects = valueGroups.map(function(values){
    return values.reduce(function(obj, value, index){
        obj[keys[index]] = value;
    return obj;
  }, {});
});

console.log(studentObjects);

https://jsfiddle.net/mjL9c7wt/

derp
  • 2,300
  • 13
  • 20
-1

Simple Javascript solution :

 var request =  {
      "student": [
        [
          "name",
          "age"
        ],
        [
          "Tom",
          12
        ],
        [
          "Jack",
          13
        ]
      ]
    };

var students = [];
for(var x = 1; x<request.student.length;x++)
{
  var temp = { 'name' : request.student[x][0],
               'age' : request.student[x][1]
             }
    students.push(temp);
}
request = { 'students' : students}

console.log(request);
Tirthraj Barot
  • 2,671
  • 2
  • 17
  • 33
  • 2
    I don't think you should hardwire in the names of the `name` and `age` properties. –  Jun 27 '16 at 05:26