在JSON中解析引用:Javascript / JSON

时间:2022-08-23 00:14:59

I have the following sample JSON coming from a server. Duplicate objects are being internally referred to by an id (see the JSON below).

我有来自服务器的以下示例JSON。 ID内部引用了重复的对象(请参阅下面的JSON)。

[
  { "id": 1,
    "agent": {
      "id": 1,
      "firstName": "gghg",
      "lastName": "gh",
      "phone": "4543534",
      "admin": true
    },
    "user":"agent@gmail.com"
  },
  { "id": 2,
    "agent": 1, // here I want the full object and not the Id
    "user":"agent1@gmail.com"
  }
]

Question: How do I resolve the objects referred to in this fashion given a random JSON object?

问题:如何在给定随机JSON对象的情况下解析以此方式引用的对象?

(For instance, for the sample JSON above, I will have the below output:)

(例如,对于上面的示例JSON,我将得到以下输出:)

[
  { "id": 1,
    "agent": {
      "id": 1,
      "firstName": "gghg",
      "lastName": "gh",
      "phone": "4543534",
      "admin": true
    },
    "user":"agent@gmail.com"
  },
  { "id": 2,
    "agent": {
      "id": 1,
      "firstName": "gghg",
      "lastName": "gh",
      "phone": "4543534",
      "admin": true
    },
    "user":"agent1@gmail.com"
  }
]

5 个解决方案

#1


2  

Basically a single loop proposal, which collects unresolved links and if found the it replaces the open parts with the object.

基本上是一个单循环提议,它收集未解析的链接,如果找到它,则用对象替换打开的部分。

var data = [{ "id": 1, "agent": { "id": 1, "firstName": "gghg", "lastName": "gh", "phone": "4543534", "admin": true }, "user": "agent@gmail.com" }, { "id": 2, "agent": 1, "user": "agent1@gmail.com" }];

data.forEach(function (a) {
    if (typeof a.agent === 'object') {
        this[a.agent.id] = this[a.agent.id] || {};
        this[a.agent.id].data = a.agent;
        this[a.agent.id].update && this[a.agent.id].update.forEach(function (b) {
            b.agent = a.agent;
        });
        return;
    } 
    this[a.agent] = this[a.agent] || {};
    if (this[a.agent].data) {
        a.agent = this[a.agent].data;
        return;
    }
    this[a.agent].update = this[a.agent].update || [];
    this[a.agent].update.push(a);
}, Object.create(null));

console.log(data);

Edit, a more generic version for unknown property references.

编辑,未知属性引用的更通用版本。

var data = [
        { id: 1, agent: { id: 1, firstName: "gghg", lastName: "gh", phone: "4543534", admin: true }, user: "agent@gmail.com", abc: 2 },
        { id: 2, agent: 1, user: "agent1@gmail.com", abc: { id: 2, text: 'blabla' } },
        { id: 3, agent: { id: 1, firstName: "gghg", lastName: "gh", phone: "4543534", admin: true }, user: "agent@gmail.com" },
    ];

data.forEach(function (a) {
    Object.keys(a).forEach(function (k) {
        if (typeof a[k] === 'object' && 'id' in a[k]) {
            this[a[k].id] = this[a[k].id] || {};
            this[a[k].id].data = a[k];
            this[a[k].id].update && this[a[k].id].update.forEach(function (b) {
                b[k] = a[k];
            });
            return;
        }
        this[a[k]] = this[a[k]] || {};
        if (this[a[k]].data) {
            a[k] = this[a[k]].data;
            return;
        }
        this[a[k]].update = this[a[k]].update || [];
        this[a[k]].update.push(a);
    }, this);
}, Object.create(null));

console.log(data);

#2


0  

try this

var data  = [
  { "id": 1,
    "agent": {
      "id": 1,
      "firstName": "gghg",
      "lastName": "gh",
      "phone": "4543534",
      "admin": true
    },
    "user":"agent@gmail.com"
  },
  { "id": 2,
    "agent": 1, // here I want the full object and not the Id
    "user":"agent1@gmail.com"
  }
];
var map = {};
//create a map of items by their id
data.forEach( function(obj){ map[ obj.id ] = obj.agent; } );

//iterate the data array and replace agents by their value if their value is a number.
data = data.map( function(obj){
  if ( !isNaN( obj.agent ) )
  {
     obj.agent = JSON.parse( JSON.stringify( map[ obj.agent ] ) );
  }
  return obj;
});

console.log( data );

#3


0  

I think the only way is to run through the array two times:

我认为唯一的方法是两次运行数组:

UPD:

var arr = [ ... ]; // your list of data
var collectionFields = ['agent', 'someOtherField'];
var collections = {};
// collect all information about agents
for (var i = 0; i < arr.length; i++) {
  var item = arr[i];
  for (var k = 0; k < collectionFields.length; k++) {
    var field = collectionFields[k];
    if (typeof collections[field] === 'undefined') {
      collections[field] = {};
    }
    if (typeof item[field] === 'object') {
      collections[field][item[field].id] = item[field];
    }
  }
}

for (var j = 0; j < arr.length; j++) {
  for (var k = 0; k < collectionFields.length; k++) {
    var field = collectionFields[k];
    if (typeof arr[j][field] === 'number') {
      arr[j][field] = collections[field][arr[j][field]];
    }
}

console.log(arr);

#4


0  

var a = [ { "id": 1, "agent": {"id": 1, "firstName": "gghg", "lastName": "gh", "phone": "4543534", 
                        "admin": true}, "user":"agent@gmail.com"}, 
            { "id": 2, "agent": 1, "user":"agent1@gmail.com"}];

//on = $.parseJSON(a);
console.log(a);
//nsole.log(bson);
var b=[];
var mapID = [];
for(var key in a) {
    console.log(a[key].agent);
            b[key] = a[key];
    if($.isNumeric(a[key].agent)){
            var id = a[key].agent;
        b[key].agent = a[mapID[id]].agent;
    }
    mapID[a[key].id] = key;
}

console.log(b);

check working demo

检查工作演示

#5


0  

You can simply define a getter for items which has only the agent ID.

您只需为只有代理ID的项目定义一个getter。

var data = [{ "id": 1, "agent": { "id": 1, "firstName": "gghg", "lastName": "gh", "phone": "4543534", "admin": true }, "user": "agent@gmail.com" }, { "id": 2, "agent": 1, "user": "agent1@gmail.com" }];

console.clear();
data.forEach((hash => d => {
  var agent = d.agent;
  if (typeof agent === 'number')
    Object.defineProperty(d, 'agent', {
      get: () => hash[agent]
    });
  else
    hash[agent.id] = agent;
})(Object.create(null)));

console.log(data);

#1


2  

Basically a single loop proposal, which collects unresolved links and if found the it replaces the open parts with the object.

基本上是一个单循环提议,它收集未解析的链接,如果找到它,则用对象替换打开的部分。

var data = [{ "id": 1, "agent": { "id": 1, "firstName": "gghg", "lastName": "gh", "phone": "4543534", "admin": true }, "user": "agent@gmail.com" }, { "id": 2, "agent": 1, "user": "agent1@gmail.com" }];

data.forEach(function (a) {
    if (typeof a.agent === 'object') {
        this[a.agent.id] = this[a.agent.id] || {};
        this[a.agent.id].data = a.agent;
        this[a.agent.id].update && this[a.agent.id].update.forEach(function (b) {
            b.agent = a.agent;
        });
        return;
    } 
    this[a.agent] = this[a.agent] || {};
    if (this[a.agent].data) {
        a.agent = this[a.agent].data;
        return;
    }
    this[a.agent].update = this[a.agent].update || [];
    this[a.agent].update.push(a);
}, Object.create(null));

console.log(data);

Edit, a more generic version for unknown property references.

编辑,未知属性引用的更通用版本。

var data = [
        { id: 1, agent: { id: 1, firstName: "gghg", lastName: "gh", phone: "4543534", admin: true }, user: "agent@gmail.com", abc: 2 },
        { id: 2, agent: 1, user: "agent1@gmail.com", abc: { id: 2, text: 'blabla' } },
        { id: 3, agent: { id: 1, firstName: "gghg", lastName: "gh", phone: "4543534", admin: true }, user: "agent@gmail.com" },
    ];

data.forEach(function (a) {
    Object.keys(a).forEach(function (k) {
        if (typeof a[k] === 'object' && 'id' in a[k]) {
            this[a[k].id] = this[a[k].id] || {};
            this[a[k].id].data = a[k];
            this[a[k].id].update && this[a[k].id].update.forEach(function (b) {
                b[k] = a[k];
            });
            return;
        }
        this[a[k]] = this[a[k]] || {};
        if (this[a[k]].data) {
            a[k] = this[a[k]].data;
            return;
        }
        this[a[k]].update = this[a[k]].update || [];
        this[a[k]].update.push(a);
    }, this);
}, Object.create(null));

console.log(data);

#2


0  

try this

var data  = [
  { "id": 1,
    "agent": {
      "id": 1,
      "firstName": "gghg",
      "lastName": "gh",
      "phone": "4543534",
      "admin": true
    },
    "user":"agent@gmail.com"
  },
  { "id": 2,
    "agent": 1, // here I want the full object and not the Id
    "user":"agent1@gmail.com"
  }
];
var map = {};
//create a map of items by their id
data.forEach( function(obj){ map[ obj.id ] = obj.agent; } );

//iterate the data array and replace agents by their value if their value is a number.
data = data.map( function(obj){
  if ( !isNaN( obj.agent ) )
  {
     obj.agent = JSON.parse( JSON.stringify( map[ obj.agent ] ) );
  }
  return obj;
});

console.log( data );

#3


0  

I think the only way is to run through the array two times:

我认为唯一的方法是两次运行数组:

UPD:

var arr = [ ... ]; // your list of data
var collectionFields = ['agent', 'someOtherField'];
var collections = {};
// collect all information about agents
for (var i = 0; i < arr.length; i++) {
  var item = arr[i];
  for (var k = 0; k < collectionFields.length; k++) {
    var field = collectionFields[k];
    if (typeof collections[field] === 'undefined') {
      collections[field] = {};
    }
    if (typeof item[field] === 'object') {
      collections[field][item[field].id] = item[field];
    }
  }
}

for (var j = 0; j < arr.length; j++) {
  for (var k = 0; k < collectionFields.length; k++) {
    var field = collectionFields[k];
    if (typeof arr[j][field] === 'number') {
      arr[j][field] = collections[field][arr[j][field]];
    }
}

console.log(arr);

#4


0  

var a = [ { "id": 1, "agent": {"id": 1, "firstName": "gghg", "lastName": "gh", "phone": "4543534", 
                        "admin": true}, "user":"agent@gmail.com"}, 
            { "id": 2, "agent": 1, "user":"agent1@gmail.com"}];

//on = $.parseJSON(a);
console.log(a);
//nsole.log(bson);
var b=[];
var mapID = [];
for(var key in a) {
    console.log(a[key].agent);
            b[key] = a[key];
    if($.isNumeric(a[key].agent)){
            var id = a[key].agent;
        b[key].agent = a[mapID[id]].agent;
    }
    mapID[a[key].id] = key;
}

console.log(b);

check working demo

检查工作演示

#5


0  

You can simply define a getter for items which has only the agent ID.

您只需为只有代理ID的项目定义一个getter。

var data = [{ "id": 1, "agent": { "id": 1, "firstName": "gghg", "lastName": "gh", "phone": "4543534", "admin": true }, "user": "agent@gmail.com" }, { "id": 2, "agent": 1, "user": "agent1@gmail.com" }];

console.clear();
data.forEach((hash => d => {
  var agent = d.agent;
  if (typeof agent === 'number')
    Object.defineProperty(d, 'agent', {
      get: () => hash[agent]
    });
  else
    hash[agent.id] = agent;
})(Object.create(null)));

console.log(data);