Use function to rewrite JSON object keys? - javascript

I have a program and want to change the object key names in a JSON file with a function. I have already created a function that changes the keys when it is displayed via Angular, but I want to create a function that allows me to change the object key names directly in the JSON file.
Here is a sample of my JSON file ( the actual array contains over 300 entries ):
[
{
"FIELD1":"key",
"FIELD2":"company",
"FIELD3":"team",
"FIELD4":"num_female_eng",
"FIELD5":"num_eng",
"FIELD6":"percent_female_eng",
"FIELD7":"last_updated",
"FIELD8":"Submit more data!",
"FIELD9":"https://github.com/triketora/women-in-software-eng"
},
{
"FIELD1":"all",
"FIELD2":"ALL",
"FIELD3":"N/A",
"FIELD4":"2798",
"FIELD5":"14810",
"FIELD6":"18.89",
"FIELD7":"11/18/2015",
"FIELD8":"",
"FIELD9":""
},
{
"FIELD1":"wellsfargo",
"FIELD2":"Wells Fargo",
"FIELD3":"N/A",
"FIELD4":"1296",
"FIELD5":"5407",
"FIELD6":"23.97",
"FIELD7":"7/22/2015",
"FIELD8":"",
"FIELD9":""
}
]
and what I have done thus far to change the key names:
(function() {
'use strict';
angular
.module("app.companies")
.controller('CompaniesCtrl', CompaniesCtrl);
CompaniesCtrl.$inject = ['$scope', 'CompanyFactory'];
function CompaniesCtrl($scope, CompanyFactory) {
$scope.work = "i work";
$scope.companies = CompanyFactory;
$scope.makeChart = function(company){
$scope.femaleDevs = parseInt(company.num_female_eng);
$scope.allDevs = parseInt(company.num_eng);
$scope.company = company.company;
$scope.maleDevs = $scope.allDevs - $scope.femaleDevs;
console.log($scope.maleDevs);
};
}
})();
Thank you for all of your help :) !

Maybe this should help you:
var fieldsmap = {
'FIELD1': 'key',
'FIELD2': 'company',
'FIELD3': 'team',
'FIELD4': 'num_female_eng',
'FIELD5': 'num_eng',
'FIELD6': 'percent_female_eng',
'FIELD7': 'last_updated',
'FIELD8': 'name2',
'FIELD9': 'name3'
};
function renameObjectKeys(obj) {
for (var key in fieldsmap) {
if (obj.hasOwnProperty(key) && fieldsmap.hasOwnProperty(key)) {
obj[fieldsmap[key]] = obj[key]; //copy the key into new key
delete(obj[key]); // delete old key
}
}
}
myArray.forEach(function(object) {
renameObjectKeys(object);
});

Related

Javascript forEach where value equals value in different array

Javascript:
$(document).ready(function() {
const ores = "../js/json/oreList.json";
const priceURL = "https://esi.tech.ccp.is/latest/markets/prices/?datasource=tranquility";
let oreArray = [];
let priceArray = [];
let total = 0;
// Retrieve list of ores
function getOres() {
$.getJSON(ores, function(ores) {
ores.forEach(function(ore) {
total++;
if (total === 48) {
getPrices();
}
oreArray.push(ore);
});
});
}
// Retrieve all items & prices via API
function getPrices() {
$.getJSON(priceURL, function(prices) {
prices.forEach(function(data) {
priceArray.push(data);
console.log(data);
});
});
}
getOres();
});
The first function creates an internal array from my .JSON file and the second function creates an internal array from the URL.
In the first array oreArray, an object looks like this:
{ id: 1234, name: "Title" }
In the second array priceArray, an object looks like this:
{ type_id: 1234, average_price: 56.34 }
My oreArray has 48 objects and unfortunately the priceArray has about 11,000 objects. I need to create a new array by comparing the two arrays and building new objects, where the ID's match. So for example objects in newArray would look like:
{ id: 1234, name: "Title", average_price: 56.34 }
Basically I'm having trouble figuring out the logic for:
For each object in oreArray, find the object with the same ID value in priceArray and append the new array with a new object using values from both arrays.
I would do it this way:
const ores = "../js/json/oreList.json",
priceURL = "https://esi.tech.ccp.is/latest/markets/prices/?datasource=tranquility";
let oreArray,
priceArray,
joinedArray = [];
function getOres() {
$.getJSON(ores, function(ores) {
oreArray = ores;
getPrices();
});
}
function getPrices() {
$.getJSON(priceURL, function(prices) {
priceArray = prices;
joinPrices();
});
}
function joinPrices() {
oreArray.forEach(function(ore) {
var matchingPrice = getMatchingPrice(ore);
if(matchingPrice !== false) {
joinedArray.push({
id: ore.id,
name: ore.name,
average_price: matchingPrice.average_price
});
}
});
}
function getMatchingPrice(ore) {
for(var i=0; i<priceArray.length; i++) {
if(priceArray[i].type_id === ore.id) {
return priceArray[i];
}
}
return false;
}
getOres();
I think that a good way to approach this problem is by changing the data structure of the average prices a little bit.
Instead of having them in an array, where each item has type_id and average_price field, you might want to consider using an object to store them, where the key is the type_id and the value is the average_price.
To be more concrete, you can replace:
prices.forEach(function(data) {
priceArray.push(data);
});
With:
const pricesMap = {};
prices.forEach(price => {
pricesMap[price.type_id] = price.average_price
});
And when looping on the oreArray, you can access each product's average_price by simply referring to pricesMap[ore.id]
You can check out this JSBin: http://jsbin.com/fogayaqexe/edit?js,console
You can use reduce to loop over each oreArr item and collect the data you need in the accumulator:
var oreArr=[
{ id: 1234, name: "Title" },
{ id: 2234, name: "2Title" },
]
var priceArr= [
{ type_id: 1234, average_price: 56.34 },
{ type_id: 2234, average_price: 256.34 },
{ type_id: 3234, average_price: 56.34 },
{ type_id: 4234, average_price: 56.34 },
]
var resArr = oreArr.reduce((ac,x) => {
var priceMatch = priceArr.find( z => z.type_id === x.id )
if(! priceMatch)
return ac //bail out if no priceMatch found
var res = Object.assign({}, x, priceMatch)
ac.push(res)
return ac
},[])
console.log(resArr)
other methods used:
arrayFind to check intersection
Object.assign to create the merged object to populate the accumulator
I suggest you to change your small json as object
eg : '{"1234":{"id": 1234, "name": "Title" }}';
var json = '{"1234":{"id": 1234, "name": "Title" }}';
oreArray = JSON.parse(json);
alert(oreArray['1234'].name); // oreArray[priceArraySingle.id].name
we can easily match priceArray id with oreArray.

Get schema of object according to JSON files

I have a huge collection of JSON files, extracted from a public API. I'm trying to get the schema of the object the files are describing (key/type of value) thanks to Node.js, the same way schemas are described in Mongoose, e.g. :
schema = {
key1: 'Number',
key2: 'Boolean',
key3: {
key31: 'String',
key32: 'Boolean'
},
key4: [{
key41: 'String',
key42: 'Number'
}]
};
In order to do this, I wrote a script which take the first file, get the keys and type of values (recursively, as the object has sub-objects) ; then compare the second file to the first one and add some data if the first file was missing some keys, and so on... Maybe not the best solution to achieve what I want to do, but it (almost) does the work.
Unfortunately, after running the script, all the types of array of sub-objects (key41 and key42 in example above) are shown as string, although I have some boolean,number ...
Here's what I did from now on :
var glob = require('glob'),
_ = require('lodash');
function getSchema(from, to) {
for (var kay in from) {
if (from.hasOwnProperty(key)) {
if (_.isObject(from[key])) {
//_.isObject() returns true for arrays
if (_.isArray(from[key])) {
if (!to.hasOwnProperty(key)) {
to[key] = [{}];
}
if (from[key].length) {
var tmp = {};
for (var i = 0; i < from[key].length; i++) {
getSchema(from[key][i], tmp);
}
getSchema(tmp, to[key][0]);
}
} else {
if (!to.hasOwnProperty(key)) {
to[key] = {};
}
getSchema(from[key], to[key]);
}
} else {
to[key] = typeof from[key];
}
}
}
};
glob('./data/**/*.json', {}, function(err, files) {
if (err) console.log(err);
var schema = {};
_.forEach(files, function(file) {
var data = require(file);
getSchema(data, schema);
});
//schema should be an object, mirroring the schema of the JSON files
});
Can someone help me fixing this ?
Thanks in advance.
Your final statement,
to[key] = typeof from[key];
should be
to[key] = from[key]
unless I am reading this wrong and the example key:value pairs contains actual values for the 'value' and not the typeof.

filter JSON by two different values

I'm using a function to filter a JSON file based on the value of the year key, like so:
function filterYr(json, key, value) {
var result = [];
for (var year in json) {
if (json[year][key] === value) {
result.push(json[year]);
}
}
return result;
}
I'm then setting a default:
var chooseYear = filterYr(json, 'year', "2000");
However there's also a dropdown, so the JSON file can be filtered onchange of the dropdown select option.
My question is, can I use this same function to filter the same JSON file by another value, too?
So for instance, I also want to filter by the key 'type.'
If it were a new function it'd be:
function filterType(json, key, value) {
var result = [];
for (var type in json) {
if (json[type][key] === value) {
result.push(json[type]);
}
}
return result;
}
But how do I combine that into one function?
And then how do I set a default that passes both the 'type' and the 'year' to the function?
Is that possible?
Thank you and let me know if I can provide more detail if this isn't clear.
PS- I'd prefer to just use javascript and not a library, if possible.
If your data structure is like below, your current function just works well
var items = [
{
year: 2000,
type: 'type1'
},
{
year: 2001,
type: 'type2'
}
];
function filterYr(json, key, value) {
var result = [];
for (var year in json) {
if (json[year][key] === value) {
result.push(json[year]);
}
}
return result;
}
filterYr(items, 'type', 'type2'); //[ { year: 2001, type: 'type2' } ]
filterYr(items, 'year', 2000); //[ { year: 2000, type: 'type1' } ]
You just need to use a more general name for your function and year variable
You can modify the function so it accepts an object as criterion for filtering. The following function accepts an object with n number of properties:
function findWhere(collection, props) {
var keys = Object.keys(props), // get the object's keys
klen = keys.length; // cache the length of returned array
return collection.filter(function(el) {
// compare the length of the matching properties
// against the length of the passed parameters
// if both are equal, return true
return keys.filter(function(key) {
return el[key] === props[key];
}).length === klen;
})
}
var filteredCollection = findWhere(arrayOfObjects, {
type: 'foo',
anotherProp: 'aValue'
});

How to convert an object of objects to an array of objects?

I have an external file people.json. How I can convert it to a javascript array with json syntax?
this is the people.json content:
{
"1":{
"Name":"Jhon",
"Surname":"Kenneth",
"mobile":329129293,
"email":"jhon#gmail.com"
},
"2":{
"Name":"Thor",
"Surname":"zvalk",
"mobile":349229293,
"email":"thor#gmail.com"
},
"3":{
"Name":"Mila",
"Surname":"Kvuls",
"mobile":329121293,
"email":"mila#gmail.com"
}
}
I want an array with this format
var person = [
{ "name":"jhon" , "surname":"kenneth", "mobile":329129293, "email":"jhon#gmail.com"},
{ "Name":"Thor", "Surname":"zvalk", "mobile":349229293, "email":"thor#gmail.com" },
{ "Name":"Mila", "Surname":"Kvuls", "mobile":329121293, "email":"mila#gmail.com"}
];
I tried with the next code, but it doesnt worker:
var person;
$.getJSON('people.json', function (json) {
person[]= json
});
By the way, the file contacts.json is in my server.
Can use jQuery $.map()
var newArray=$.map( originalObject, function(item){
return item;
})
DEMO: http://jsfiddle.net/qmfn2/
Try like this:
$.getJSON('people.json', function (json) {
var people = [];
for (var key in json) {
if (json.hasOwnProperty(key)) {
var item = json[key];
people.push({
name: item.Name,
surname: item.Surname,
mobile: item.mobile,
email: item.email
});
}
}
// at this stage the people object will contain the desired output
});
First you will need to fetch the JSON file using an AJAX request. Then iterate through the received JSON object and add each property to an array.
function convertToArray (receivedObj) {
var array = [], key;
for (key in receivedObj) {
array.push(receivedObj[key]);
}
return array;
}
$.getJSON('people.json', function (json) {
var array = convertToArray(json);
});
Hope this helps!
Like this:
var array = $.map($.parseJSON(data), Object);
http://jsfiddle.net/mXFKL/
$.getJSON('people.json', function (json) {
var array = convertToArray(json);
});

Creating associative arrays in JavaScript

Using the following code:
$credits.getCredits = function() {
return $(this).find( 'tbody' ).children( 'tr' ).map(function(){
var $name = $(this).children(':first').html();
var $role = $(this).children(':nth-child(2)').html();
return { $role: $name };
}).get();
}
Which looks through the elements of a credits list and should return a listing like the following:
[
{ 'Make-up': 'Bob' },
{ 'Make-up': 'Susan' },
{ 'Photography': 'Charlie' },
{ 'Lighting': 'Mike' },
{ 'Props': 'One-handed Tony' }
]
It ends up outputting this instead:
[
{ '$role': 'Bob' },
{ '$role': 'Susan' },
{ '$role': 'Charlie' },
{ '$role': 'Mike' },
{ '$role': 'One-handed Tony' }
]
How do you remedy the associative array creation to get the desired output?
Create the object (associative array) in two steps:
var obj = {};
obj[$role] = $name;
return obj
Whenever you use literals to create an object ({foo: bar}), the key will also be taken literally and will not be evaluated.
You need to return it a little differently if you want a dynamic name, like this:
$credits.getCredits = function() {
return $(this).find( 'tbody' ).children( 'tr' ).map(function(){
var $name = $(this).children(':first').html(),
$role = $(this).children(':nth-child(2)').html(),
result = {};
result[$role] = $name;
return result;
}).get();
}
You can try an example here (check the console). This is, well, just the way object literal syntax works. Since these are equivalent:
object.propertyName
object["propertyName"]
You can assign via that same route.
There are no associative arrays in JS. Just create a new object and assign like you want, e.g:
var $obj = {};
$obj.MakeUp = 'Bob';

Categories