I would like to replicate this example data set into nested JSON using JavaScript or Angularjs or any javascript library.
Data:
PrimaryId,FirstName,LastName,City,CarName,DogName
100,John,Smith,NewYork,Toyota,Spike
100,John,Smith,NewYork,BMW,Spike
100,John,Smith,NewYork,Toyota,Rusty
100,John,Smith,NewYork,BMW,Rusty
101,Ben,Swan,Sydney,Volkswagen,Buddy
101,Ben,Swan,Sydney,Ford,Buddy
101,Ben,Swan,Sydney,Audi,Buddy
101,Ben,Swan,Sydney,Volkswagen,Max
101,Ben,Swan,Sydney,Ford,Max
101,Ben,Swan,Sydney,Audi,Max
102,Julia,Brown,London,Mini,Lucy
Javascript:
var file = reader.result;
var singleRow = readerFile.split(/\r\n|\n/);
var header = singleRow[0].split(',');
var result =[];
for ( var i=1; i < file.length; i++ ){
var elementData = singleRow[i].split(',');
elementData = elementData.filter(function(n){ return n != "" });
var Obj = {};
for ( var j=0; j < header.length; j++ ){
Obj[header[j]] = elementData[j];
/*
- How can i build child object and append back to Obj before j loop
- How can i build multiple child for same parent
*/
}
result.push(Obj);
}
console.log(" Print the JSON Object : " + JSON.stringify(result));
Desired Output:
{
"data": [
{
"City": "NewYork",
"FirstName": "John",
"PrimaryId": 100,
"LastName": "Smith",
"CarName": [
"Toyota",
"BMW"
],
"DogName": [
"Spike",
"Rusty"
]
},
{
"City": "Sydney",
"FirstName": "Ben",
"PrimaryId": 101,
"LastName": "Swan",
"CarName": [
"Volkswagen",
"Ford",
"Audi"
],
"DogName": [
"Buddy",
"Max"
]
},
{
"City": "London",
"FirstName": "Julia",
"PrimaryId": 102,
"LastName": "Brown",
"CarName": [
"Mini"
],
"DogName": [
"Lucy"
]
}
]
}
If Firstname, Lastname and City has same values then CarName and DogName values should be child object under the same parent
I reformatted your initial code a little bit, but it doesn't change the initial logic. One key observation is that even if the FirstName, LastName and City are the same, that may not be a unique person, hence you should use the PrimaryId instead, to determine uniqueness.
Look at the post-processing section for the new code:
const data = `PrimaryId,FirstName,LastName,City,CarName,DogName
100,John,Smith,NewYork,Toyota,Spike
100,John,Smith,NewYork,BMW,Spike
100,John,Smith,NewYork,Toyota,Rusty
100,John,Smith,NewYork,BMW,Rusty
101,Ben,Swan,Sydney,Volkswagen,Buddy
101,Ben,Swan,Sydney,Ford,Buddy
101,Ben,Swan,Sydney,Audi,Buddy
101,Ben,Swan,Sydney,Volkswagen,Max
101,Ben,Swan,Sydney,Ford,Max
101,Ben,Swan,Sydney,Audi,Max
102,Julia,Brown,London,Mini,Lucy`;
var singleRow = data.split(/\r\n|\n/);
var header = singleRow[0].split(',');
var result =[];
for (var i = 1; i < singleRow.length; i++) {
var elementData = singleRow[i].split(',');
elementData = elementData.filter(function(n) { return n != '' });
var Obj = {};
for ( var j=0; j < header.length; j++ ){
Obj[header[j]] = elementData[j];
}
result.push(Obj);
}
console.log(JSON.stringify(result, null, 2));
// Post-processing code starts here
const people = {};
// Create a map of unique people first
result.forEach(function (object) {
if (!people[object.PrimaryId]) {
people[object.PrimaryId] = {
City: object.City,
FirstName: object.FirstName,
PrimaryId: object.PrimaryId,
LastName: object.LastName,
CarName: [],
DogName: [],
};
}
// As you iterate through your results, if this person already exists
// add to their array of car and dogs.
people[object.PrimaryId].CarName.push(object.CarName);
people[object.PrimaryId].DogName.push(object.DogName);
});
// Convert back into an array
const peopleList = [];
Object.keys(people).forEach(function (primaryId) {
peopleList.push(people[primaryId]);
})
console.log(peopleList);
First of all, since you already know the property names, there's no point in parsing the first row.
I would do something like this:
let results = {};
for (let i = 1; i < file.length; i++) {
let entry = getEntry(results, file[i][0]);
entry.DogName.push(file[i][DOGNAME_INDEX]);
entry.CarName.push(file[i][CARNAME_INDEX]);
entry.LastName = file[i][LASTNAME_INDEX];
...
}
// and now to convert this into an array
let array = Object.keys(results).map(key => results[key]);
// retrieves or creates an entry for a given primary key
function getEntry(results, id) {
return results[id] || (results[id] = {});
}
You could also get fancier and dynamically determine what the column indexes are, but the way I have it just keeps things simple.
Made a fiddle for you, it gives the desired output with some things in a different order than you presented.
You can save the indexes of the headers:
var Index = {};
for(var k = 0; k < header.length; k++)
{
Index[header[k]] = k;
}
And keep a list of cities:
var cities = [];
....
cities.push(data[Index["City"]]);
To use for later so that you don't keep making more objects if the city already exists:
obj = result.data[cities.indexOf(data[Index["City"]])];
The JSFiddle: https://jsfiddle.net/3u28aon3/1/
I need to loop through array and each array in array that has extra values, push them to their parent array as separate item. I hope this makes sense..
This is the structure of my initial array:
{type:
[ 0:
value: "tomato"
],
[ 1:
{value: "apple",
[ extras:
[ 0: { value: "green" } ],
[ 1: { value: "red" } ]
]
],
[ 2:
value: "pineapple"
]
}
What the result would have to look like:
[type:
[ 0:
tomato
],
[ 1:
apple,
green,
red
],
[ 2:
pineapple
]
]
What I've tried and failed: (I also commented the error I get on right line)
var response = /* json of first codeblock in question is response from ajax */;
var items = JSON.parse( response );
var type = Object.keys( items )[0];
var myArray = []
var count = items[type].lenght;
//Loop through main items in "type"
for( i = 0; i < count; i++ ) {
var value = items[type][i][value];
myArray[type][i] = [value]; //Uncaught TypeError: Cannot set property '0' of undefined
if( items[type][i][extras] ) {
var extracount = items[type][i][extras].lenght;
//Loop through extras
for( k = 0; k < extracount; k++ ) {
var extra = items[type][i][extras][k][value];
myArray[type][i].push( extra );
}
}
}
My main problem that I don't understand and that seems to be the problem in my example as well:
If I declare an empty array, how do I:
push an item to that array also declaring a new array around that item?
push another item to that array that was made around the first item?
This is what I believe you want. The following code may be incorrect, because I'm approximating what I believe your items object contains.
var items = {
type: [
{
value: "tomato"
},
{
value: "apple",
extras: [
{
value: "green"
}, {
value: "red"
}
]
},
{
value: "pineapple"
}
]
};
var myArray = {
type: []
};
var count = items['type'].length;
//Loop through main items in "type"
for (i = 0; i < count; i++) {
var subarray = [];
subarray.push(items['type'][i]['value']);
if (items['type'][i]['extras']) {
var extracount = items['type'][i]['extras'].length;
//Loop through extras
for (k = 0; k < extracount; k++) {
var extra = items['type'][i]['extras'][k]['value'];
subarray.push(extra);
}
}
myArray['type'].push(subarray);
}
Some notes:
You will definitely need to learn the difference between an array and an object in javascript. There are plenty of resources online for this.
When retrieving/manipulating a property prop from an object obj (i.e. for a key-value pair), you will need to use obj.prop or obj['prop']. Note the use of a string in the latter example.
For an array arr, you should use arr.push(value) to push a new value onto the array.
Your problem is here:
var value = items[type][i][value];
you should change it to
var value = items[type][i].value;
I want to add javascript array values into JSON values object. The other element is also replaced my element like recipients, subject, message. I got Json like:
Below is my code.
var BODY = {
"recipients": {
"values": [
]
},
"subject": title,
"body": message
}
var values = [];
for (var ln = 0; ln < names.length; ln++) {
var item1 = {
"person": {
"_path": "/people/"+names[ln],
},
};
values.push(item1);
}
BODY = JSON.stringify({values: values});
alert(BODY);
I think you want to make objects from array and combine it with an old object (BODY.recipients.values), if it's then you may do it using $.extent (because you are using jQuery/tagged) method after prepare the object from array
var BODY = {
"recipients": {
"values": []
},
"subject": 'TitleOfSubject',
"body": 'This is the message body.'
}
var values = [],
names = ['sheikh', 'muhammed', 'Answer', 'Uddin', 'Heera']; // for testing
for (var ln = 0; ln < names.length; ln++) {
var item1 = {
"person": { "_path": "/people/"+names[ln] }
};
values.push(item1);
}
// Now merge with BODY
$.extend(BODY.recipients.values, values);
DEMO.
If you want to stick with the way you're populating the values array,
you can then assign this array like so:
BODY.values = values;
after the loop.
It should look like this:
var BODY = {
"recipients": {
"values": [
]
},
"subject": title,
"body": message
}
var values = [];
for (var ln = 0; ln < names.length; ln++) {
var item1 = {
"person": {
"_path": "/people/"+names[ln],
},
};
values.push(item1);
}
BODY.values = values;
alert(BODY);
JSON.stringify() will be useful once you pass it as parameter for an AJAX call.
Remember: the values array in your BODY object is different from the var values = [].
You must assign that outer values[] to BODY.values. This is one of the good things about OOP.
You can directly access BODY.values:
for (var ln = 0; ln < names.length; ln++) {
var item1 = {
"person": {
"_path": "/people/"+names[ln],
},
};
BODY.values.push(item1);
}
var arr = [ 'a', 'b', 'c'];
arr.push('d'); // insert as last item
var d=getEntity( {"Division":
{
"oddTerms":
[
{
"entity": "Sunshine",
"Sunshine": [
{
"count": 2,
"entity": "Dodge"
},
{
"count": 1,
"entity": "Dodge Avenger"
},
]
}
]
}});
I want to traverse through the json string and the the entity names Dodge and Dodge Avenger. Ive used the following method
for (var k in h.Division.oddTerms)
{
s=h.Division.oddTerms[k].entity;
h.Division.oddTerms[k].+s+.entity;
}
But I do think this its not the correct methd to concatenate as it is not wrking.. anyone knows the correct format?
oddTerms is an Array, not an Object. For arrays in JavaScript you need to use a for loop with a counter instead of iterating through the elements:
var concatedString = '';
for (var k=0; k<h.Division.oddTerms.length;k++)
{
// Get the name of the entity we want to collect the entity terms of
var entityName =h.Division.oddTerms[k].entity;
// iterate through all the instances of each entity
for(var j=0; j<h.Division.oddTerms[k][entityName].length;j++){
concatedString += h.Division.oddTerms[k][entityName][j].entity;
}
}
var entityName = "",
arrTerms = [],
outputTemplate = '{"%entityName":[%terms]}',
h = {
"Division":
{
"oddTerms":
[
{
"entity": "Sunshine",
"Sunshine": [
{
"count": 2,
"entity": "Dodge"
},
{
"count": 1,
"entity": "Dodge Avenger"
},
]
}
]
}
};
for (var i = 0; i < h.Division.oddTerms.length; i++)
{
entityName=h.Division.oddTerms[i].entity; // "Sunshine"
terms = h.Division.oddTerms[i][entityName];
for (var j = 0; j < terms.length; j++) {
arrTerms.push('"' + terms[j].entity + '"');
}
}
// This will give you '{"Sunshine":["Dodge","Dodge Avenger"]}':
console.log(outputTemplate.replace('%entityName', entityName).replace('%terms', arrTerms.join(",")));
Edit:
Just some more on this.
JSON can be a bit confusing to work with if you're not used to working with JS and object and array "literals". In JS you can define objects and arrays in a number of ways, but the easiest (and the most preferred, by many developers) is with these literals.
Here's an example of an object:
var myObj = {
"some prop":"some value",
"anotherProp":"another value"
}
You can look up the members of myObj in several ways:
myObj.anotherProp // "another value"
myObj["some prop"] // you have to use this form if the property name has a space in it
For looping through the contents of an array, use the second form. For example, this won't work:
for (var strPropName in myObj) {
console.log(myObj.strPropName); // This won't work!
}
Instead, you should loop through the properties like this:
for (var strPropName in myObj) {
if (myObj.hasOwnProperty(strPropName)) {
console.log(myObj[strPropName]);
}
}
The if block is optional, but you'll avoid potential problems if you always include this in your code. It's also required by some validators.
Now, here's an example of an array:
var myArray = ["some value", "anotherValue"];
You access these with a numeric index:
myArray[0] // "some value"
myArray[1] // "anotherValue"
myArray[2] // undefined
And you can loop through them:
for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}
You can nest objects inside arrays:
myArray = [{},{},{}];
And you can nest arrays inside objects:
myObject = {"arr1":[], "arr2":[], "arr3":[]}
I'm getting JSON name/value pairs that looks like this:
{
"Name":"parentid",
"Value":"blah"
},
{
"Name":"siteid",
"Value":"blah"
},
{
"Name":"sitename",
"Value":"blah"
}
But I would like to access the "name" value as the KEY, and the "value" value as the VALUE. Is there an elegant way to turn that piece of JSON into something like this?
{'parentid', 'blah'},
{'sitename', 'blah'}
Try this:
var items = [
{
"Name":"parentid",
"Value":"blah"
},
{
"Name":"siteid",
"Value":"blah"
},
{
"Name":"sitename",
"Value":"blah"
}
];
var results = new Object();
for (var i = 0; i < items.length; i++)
{
results[items[i].Name] = items[i].Value;
}
This will result in something like:
var results = { parentid: "Blah", siteid: "Blah", sitename: "Blah" };
One way to do it.
var json = [
{
"Name":"parentid",
"Value":"blah"
},
{
"Name":"siteid",
"Value":"blah"
},
{
"Name":"sitename",
"Value":"blah"
}
];
for ( var i = 0, l = json.length, obj; i < l; i++ )
{
obj = json[i];
json[i] = new Object();
json[i][obj.Name] = obj.Value;
}
// console.log() requires Firebug
console.log( json );
function objectflatten (array) {
var out = {}, i;
for(i = 0; i < array.length; i++) {
out[array[i].name] = array[i].value;
}
return out;
}
This is a function that will take an object in the form you presented, and output it as a "normal" object with the name values as keys, and the value values as values.
I'd recommend using the for( ... in ... ) method for this task. It'll grab the key names like you need.
var jsonObj = eval( '([{ "Name":"parentid", "Value":"blah" }])' );
for( var i = 0, assoc = {}, key; i < jsonObj.length; ++i )
{
for( key in jsonObj[ i ] ) // <-- this right here
{
assoc[ key ] = jsonObj[ i ][ key ];
}
}
and you end up with (from Firebug)
Object Name=parentid Value=blah
that can be accessed by object.key or object[ 'key' ] (in our case assoc.Name or assoc[ 'Value' ])
here's a link from Douglas Crockford from Yahoo! about using it as well - http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
I'm assuming you are using PHP, and the PHP echoes you assosiatice aray like this:
echo json_encode($result);
In your javascript, you could do this:
// Soemthing retrieves php result and puts it in `var result`.
data = eval("(" + result+ ")");
alert(data.parentid);
I'm not sure if this is what you want, but it's a solution.