data transformation from one form of array to another - javascript

I have doubt about data structure transformation from one form of array to another.
My input data is of the form,
var testVar=[
{
"count": 1,
"term": "Company",
"Company": [
{
"Tata": [
{
"count": 1,
"term": "Tatagroup"
}
],
"sector": "Automotive",
"type": "Car"
},
]
},
{
"count": 2,
"term": "Country",
"Country": [
{
"France": [
{
"count": 1,
"term": "France"
}
],
"region": "Europe",
"Player": "Zidane",
"term": "France",
"code": "FRA"
},
{
"region": "Europe",
"Player": "Federer",
"term": "Switzerland",
"Switzerland": [
{
"count": 1,
"term": "Switzerland"
}
],
"code": "SWI"
}
]
}];
and I am trying to transform it to the form,
[ "Tata" : [{"sector" : "automotive"}, "type" : "car"], "France": [{"region" : "Europe}, {"Player" : "Zidane"} , {"code" : "FRA"}], "switzerland" : [{"region" : "Europe}, {"Player" : "Federer"} , {"code" : "SWI"}]];
The code I came up with looks like http://jsfiddle.net/X2apw/2/, bt its nt accurate..

var testvar = [...];
var result = {};
for (var i=0; i<testvar.length; i++) {
var arr = testvar[i][testvar[i].term];
for (var j=0; j<arr.length; j++) {
var resarr = [];
for (var k in arr[j]) {
if (typeof arr[j][k] == "string") {
var obj = {};
obj[k] = arr[j][k];
resarr.push(obj);
} else {
result[k] = resarr;
}
}
}
}
(Demo at jsfiddle.net)
However, I strongly recommend to use just one object instead of an array of one-property-objects in your result format. Change the inner loop body to:
var resobj = {};
for (var k in arr[j]) {
if (typeof arr[j][k] == "string") {
resobj[k] = arr[j][k];
} else {
result[k] = resobj;
}
}
(Demo)

Related

Push elements of

This is, I believe a very simple question for a JS programmer. Given the following array of objects named "categories"
[
{
"id": 1,
"name": "FURNITURE",
},
{
"id": 2,
"name": "AUTOMOTIVE",
},
{
"id": 3,
"name": "UPHOLSTERY",
}
]
I want to push the "name" on the "selectedCategories" array below where "id" === "id"
[
{
"id": 1
},
{
"id": 3
}
]
Below is my attempt to solve this, but ... not working..
for (let i = 0; i < selectedCategories.length; i++) {
for(let y = 0; y < categories.length; y++){
selectedCategories.name = categories[y].name
}
}
I believe this is what you are looking for
selectedCategories = selectedCategories.map(el => {
const searchEl = categories.find(e => e.id === el.id);
if (searchEl)
return { ...el, name: searchEl.name }
return el;
});
const categories = [
{
"id": 1,
"name": "FURNITURE",
},
{
"id": 2,
"name": "AUTOMOTIVE",
},
{
"id": 3,
"name": "UPHOLSTERY",
}
];
var selectedCategories = [
{
"id": 1,
},
{
"id": 3,
}
];
selectedCategories = selectedCategories.map(
selectedCategory => categories.find(category => category.id === selectedCategory.id),
);
console.log(selectedCategories);

Normalize JSON to a custom schema

I have an array of objects with the following format
var arr = [
{
"productId": "123456",
"productName": "Test Product 1",
"description": [
"This is delicious",
"Suitable for vegetarian"
],
"attributes": {
"internalId": "091283"
"category": "Dairy"
},
"order": 1
}
];
And I am trying to map into something like below
[
[{
{
"name": "productId",
"value": "123456"
},
{
"name": "productName",
"value": "Test Product 1"
},
{
"name": "description",
"value": ["This is delicious", "Suitable for vegetarian"]
},
{
"name": "attributes",
"value": {
{
"name": "internalId",
"value": "091283"
},
{
"name": "category",
"value": "Dairy"
}
}
},
{
"name": "order",
"value": 1
}
}]
]
I tried mapping simple properties before going further and now stuck at getting only the last property of each object in the loop.
Suppose I don't know what are the format of incoming data and how can I normalize the JSON object to the format I want?
normalizeJson = (array) => {
for(i = 0; i < array.length; i++){
normalizedJson[i] = {};
Object.keys(array[i]).forEach(key => {
if (array[i][key] && typeof array[i][key] === "object") {
// normalizeJson(obj[key]);
// console.log(key + ' is object');
return;
} else {
o = {};
o["name"] = key;
o["value"] = array[i][key];
normalizedJson[i] = o;
// normalizedJson[i]["name"] = key;
// normalizedJson[i].value = array[i][key];
// console.log(key);
return;
}
});
}
console.log(normalizedJson);
};
Or is there any library I can use in order to achieve this?
Try this
var obj = [
{
productId: "123456",
productName: "Test Product 1",
description: ["This is delicious", "Suitable for vegetarian"],
attributes: {
internalId: "091283",
category: "Dairy",
},
order: 1,
},
];
function normalizeObject(obj) {
var result = [];
if (Array.isArray(obj)) {
for (let i of obj) {
result.push(normalizeObject(i));
}
} else if (typeof obj == "object") {
for (let i of Object.keys(obj)) {
result.push({ name: i, value: normalizeObject(obj[i]) });
}
} else {
return obj;
}
return result;
}
console.log(JSON.stringify(normalizeObject(obj), null, 2));
This looping method called recursion. Which is loop by calling function itself.

Resolve References in JSON : Javascript / JSON

I have the following sample JSON coming from a server. Duplicate objects are being internally referred to by an id (see the JSON below).
[
{ "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?
(For instance, for the sample JSON above, I will have the below output:)
[
{ "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"
}
]
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);
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 );
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);
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
You can simply define a getter for items which has only the agent ID.
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);

Updating elemint in JSON updates ALL

I have a JSON object parsed and I am trying to navigate down to SHIPPINGCOMMENTS and update it, but when I do, it updates all cells with that name instead of just the one.
{
"id": 1402846607011,
"status": "unsaved",
"accounts": [
{
"compid": 919759,
"compname": null,
"products": [
{
"BCINUM": "539504",
"ITEMUNIT": "EA",
"ORDERDETAILS": [
{
"SHIPDATEID": "69230",
"SHIPPERIODID": "2096",
"QUANTITY": "1"
},
{
"SHIPDATEID": "69231",
"SHIPPERIODID": "2096",
"QUANTITY": "2"
}
],
"SHIPPINGCOMMENTS": "sooner"
}
]
},
{
"compid": 920001,
"compname": null,
"products": [
{
"BCINUM": "539504",
"ITEMUNIT": "EA",
"ORDERDETAILS": [
{
"SHIPDATEID": "69230",
"SHIPPERIODID": "2096",
"QUANTITY": "1"
},
{
"SHIPDATEID": "69231",
"SHIPPERIODID": "2096",
"QUANTITY": "2"
}
],
"POTEXT": "",
"SHIPPINGCOMMENTS": "sooner"
}
]
}
]
}
Here is my code I am looping through it with:
function updateComments(compID,bcinum,comment) {
var accounts = runningOrders.accounts;
var n = accounts.length;
for (i = 0; i < n; i++) {
if (accounts[i].compid == compID) {
var p = accounts[i].products.length;
for (ii = 0; ii < p; ii++) {
if (accounts[i].products[ii].BCINUM == bcinum) {
accounts[i].products[ii].SHIPPINGCOMMENTS = comment;
}
}
}
}
}
The function call is:
updateComments(919759,539504,sooner);
Two potential issues:
When calculating n, you are actually not calculating the size of the acconts array? What is the name of your (JSON) object?
In your example function call, you are changing the name to the already defined name in both objects. Is this a mistake?
This code is working for me in node.js:
function updateComments(compID,bcinum,comment) {
var n = accounts.accounts.length;
console.log(n);
console.log(accounts['accounts'][0].products);
console.log(accounts['accounts'][1].products);
for (i = 0; i < n; i++) {
console.log('testing ', i, accounts.accounts[i].compid)
if (accounts.accounts[i].compid == compID) {
var p = accounts.accounts[i].products.length;
console.log('Found compid', i, compID);
for (ii = 0; ii < p; ii++) {
if (accounts.accounts[i].products[ii].BCINUM == bcinum) {
console.log('Found bcinum', ii, bcinum)
accounts.accounts[i].products[ii].SHIPPINGCOMMENTS = comment;
}
}
}
}
console.log(accounts['accounts'][0].products);
console.log(accounts['accounts'][1].products);
}
accounts = {
"id": 1402846607011,
"status": "unsaved",
"accounts":
[
{
"compid": 919759,
"compname": null,
"products": [
{
"BCINUM": "539504",
"ITEMUNIT": "EA",
"ORDERDETAILS": [
{
"SHIPDATEID": "69230",
"SHIPPERIODID": "2096",
"QUANTITY": "1"
},
{
"SHIPDATEID": "69231",
"SHIPPERIODID": "2096",
"QUANTITY": "2"
}
],
"SHIPPINGCOMMENTS": "sooner"
}
]
},
{
"compid": 920001,
"compname": null,
"products": [
{
"BCINUM": "539504",
"ITEMUNIT": "EA",
"ORDERDETAILS": [
{
"SHIPDATEID": "69230",
"SHIPPERIODID": "2096",
"QUANTITY": "1"
},
{
"SHIPDATEID": "69231",
"SHIPPERIODID": "2096",
"QUANTITY": "2"
}
],
"POTEXT": "",
"SHIPPINGCOMMENTS": "sooner"
}
]
}
]
}

traversing through json nodes

Is it possible to traverse through all the nodes and find the wanted field from a complex json whose level is not predetermined
{
"_index": "test",
"_type": "news",
"_source": {
"partnerName": "propertyFile 9",
"relatedSources": "null",
"entityCount": "50",
"Categories": {
"Types": {
"Events": [{
"count": 1,
"term": "Time",
"Time": [{
"term": "Dec 9",
"Dec_9": [{
"count": 1,
"term": "2012"
}]
}]
}, {
"count": 4,
"term": "News",
"News": [{
"term": "Germany",
"Germany": [{
"count": 1,
"term": "Election"
}],
"currency": "Euro (EUR)"
}, {
"term": "Egypt",
"Egypt": [{
"count": 1,
"term": "Revolution"
}]
}]
}]
}
}
}
}
I could get in to the first level , bt how do I go to second level if the field name is not present in the first level. This is how I started it. http://jsfiddle.net/W8qhA/1/
I hope this will solve your problem. There is some function and also a little explanation. Hope that helps you out.
Traverse all the Nodes of a JSON Object Tree with JavaScript
I whipped up a function that will work on an object of the structure you presented. If there are multiple keys of the same name it will simply return the first one it encounters.
var findDeepKey = function(obj, key){
var results = [];
if (typeof obj !== 'object') return null;
for (var k in obj) {
if (k === key) return obj[k];
}
for (var k in obj) {
if (typeof obj[k] === 'object') {
if (obj[k].length) {
for (var i = 0, il = obj[k].length; i < il; i++) {
results.push(findDeepKey(obj[k][i], key));
}
} else {
for (var kk in obj[k]) {
if (kk === key) return obj[k][kk];
results.push(findDeepKey(obj[k][kk], key));
}
}
}
}
for (var i = 0, il = results.length; i < il; i++) {
if (results[i] !== null) return results[i];
}
return null;
};
See demo
You can use http://james.newtonking.com/projects/json-net.aspx

Categories