-2

In my PHP app, for 2 different tools I get 2 json responses but I would like to use the same javascript to handle both.

All I need to do is to compare this structure

data = [
  {'k1':'v1'},
  {'k2':'v2'},
  {'k3':'v3'}
]

with this one:

data = {'k11':'v11', 'k22':'v22', 'k33':'v33'}

this must work for any number of results (they are not suppose to match) and it also needs to work if 1 result is given in any of both cases.

I've already tried - using data.length (which I thought in the second case would give me 1 array - data instanceof Array, which is true for both cases (same thing if I do data instanceof Object)

What is the best approach to compare these in javascript?

EDITED: the keys and values of both json are not suppose to match, I only want to compare the structure, or detect one of them without having the other. (array of objects vs object with properties)

w3jimmy
  • 692
  • 10
  • 21

4 Answers4

3

The first one is an array of objects; the second is an object with properties.

If you need to do this on the PHP side, just do json_decode($data, true) on the second data structure (the second argument casts it as an array) before output. You may have to play around with it a little to get the structures to line up but it should be pretty straight-forward.

Otherwise, in js -

var data = [
  {'k':'v'},
  {'k2':'v2'},
  {'k3':'v3'}
],
data2 = {'k':'v', 'k2':'v2', 'k3':'v3'},
data3 = [];

for (var x in data2) {
    data3.push({x:data2[x]});
}
OpenSorceress
  • 2,014
  • 16
  • 21
  • I prefer your php solution is way much better, suits perfectly! But since I was asking for a js solution, how could I use a simple way to detect if it's an array of objects or an object with properties only getting one of them at a time (not having another to compare)? – w3jimmy Jan 25 '14 at 15:13
  • In JS, an Array _is_ an Object. Testing for array-specific methods, like "slice" -> `if (data2.slice) would allow you to distinguish between the two. Going much farther than that without encapsulating the functionality in a function would get messy, however. – OpenSorceress Jan 27 '14 at 19:25
1

To check if the received data is in the first format or the second one you may just check if the data is an array or not.

The correct way to do it is as follows:

if( Object.prototype.toString.call( data ) === '[object Array]' )
{
    // an array: parse data according to first format
}
else
{
    // not an array: parse data according to second format
}
Paolo
  • 15,233
  • 27
  • 70
  • 91
  • sorry, but I'm just looking for a way to compare the structure, not the values. thanks anyway – w3jimmy Jan 24 '14 at 19:18
  • with the code I postes you're comparing both. "equal" evaluates true if both structure and content match. – Paolo Jan 25 '14 at 09:33
  • I only get one at a time so I don't have 2 to compare, and this is expecting the number of contents to match between the two structures which will unlikely ever happen – w3jimmy Jan 25 '14 at 15:09
  • so, when my script receives the json, how does it know which format I receive before doing any conversion? – w3jimmy Jan 25 '14 at 18:38
  • 1
    if( typeof( data.length ) != 'undefined' ) -----> FIRST FORMAT – Paolo Jan 25 '14 at 18:39
  • perfect, can you update your answer, I'll mark it as the correct one. thank you – w3jimmy Jan 25 '14 at 18:43
  • 1
    updated the answer. Also updated the way to check if the data is an array with a more safe method - from http://stackoverflow.com/questions/4775722/check-if-object-is-array – Paolo Jan 25 '14 at 21:41
1

There are several way you can do this. I would flatten the array so that it matches the format of the object:

function Flatten(source) {
    if (!source || !source.length || source.length === 0) {
        return source;
    }
    var output = {};
    for (var i = 0; i < source.length; i++) {
        for (prop in source[i]) {
            if (source[i].hasOwnProperty(prop)) {
                output[prop] = source[i][prop];
            }
        }
    }
    return output;
}

Here's a fiddle

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
0

I'm not actually sure what you mean by "compare", but if you want a purely JavaScript solution to finding out if the structures are equivalent, you could use this.

Simple Shallow Solution

function numOwnProperties (obj) {
  var i = 0;
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) { i++; }
  }
  return i;
}

function areEquivalent (obj, arr) {  

  var length = arr.length;

  if (numOwnProperties(obj) !== length) { return false; }

  for (var i = 0; i < length; i++) {
    var item = arr[i];
    for (var key in item) {
      if (item.hasOwnProperty(key) && item[key] !== obj[key]) {
        return false;
      }
    }
  }

  return true;

};

Usage

data1 = [
  {'k':'v'},
  {'k2':'v2'},
  {'k3':'v3'}
];

data2 = {
  'k':'v',
  'k2':'v2',
  'k3':'v3'
};

console.log(areEquivalent(data2, data1)); // true
cwharris
  • 17,835
  • 4
  • 44
  • 64
  • I tried this with `data3 = {'k11':'v11', 'k31':'v31'};` and `data2 = {'k1':'v1', 'k2':'v2', 'k3':'v3'};`. `console.log(areEquivalent(data2, data3));` gives false and the solution I'm looking for should give true – w3jimmy Jan 25 '14 at 00:52
  • Why should it return true? `'k1' !== 'k11'`. – cwharris Jan 25 '14 at 07:41
  • because I'm looking for a simple way of comparing the structure, I don't want to compare the values – w3jimmy Jan 25 '14 at 15:01