My JSON is like:
{
"boundaries": [
{
"boundary": {
"boundaryId": "45083021141",
"boundaryType": "USA_POSTCODE",
"boundaryRef": "B1"
}
}
],
"themes": [
{
"TheftCrimeTheme": {
"boundaryRef": "B1",
"individualValueVariable": [
{
"name": "2013 Theft Crime",
"description": "Theft Crime for 2013",
"count": 2080
}
]
}
},
{
"BurglaryCrimeTheme": {
"boundaryRef": "B1",
"individualValueVariable": [
{
"name": "2013 Burglary Crime",
"description": "Burglary Crime for 2013",
"count": 302
}
]
}
}
]
}
I want to get value of count to display in graph. As you can see in the above json, inside themes there are two keys i.e TheftCrimeTheme and BurglaryCrimeTheme. I want to get value of count in everycrimetheme. For this I did the below code:
$http.get("http://152.144.218.70:8080/USACrime/api/crimeAPI?city="+$scope.strCity+"&crimeType="+$scope.type1+"&years="+$scope.type+"&month="+$scope.type2).success(function (result) {
for(var i=0;i<result.themes.length;i++){
var crime={};
console.log("did",result.themes[i]);
var test2 = result.themes[i];
console.log("test2",test2);
var test = test2[Object.keys(test2)];
console.log("test",test);
crime.name = Object.keys(result.themes[i]);
console.log("CrimeName",crime.name);
crime.data = [];
var test1 = test.individualValueVariable[0].count;
console.log("test1",test1);
crime.data.push(test1);
crime_data.push(crime);
}
});
My agenda is to plot graph showing count of every year.To achieve this firstly I have to get multiple keys like TheftCrimeTheme, BurglaryCrimeTheme etc. Then after that i can access value of count in individualValueVariable.
when I used Object.keys() method , I got an error "undefined" when i console values of nameR. Please suggest me how should i do this?
This function recieves info (as the whole json), and theme as the theme which you want to get the count (ie.: "BurglaryCrimeTheme").
getThemeCrimesCount = (info, theme) => {
const record = info.themes.find(obj => Object.keys(obj)[0] == theme)[theme];
return record.individualValueVariable.reduce((a, b) => a += b.count, 0);
}
getThemeCrimesCount(info, "BurglaryCrimeTheme"); // 302
getThemeCrimesCount(info, "TheftCrimeTheme"); // 2080
Formatting this to separate the elements for clarity.
// Builds and returns URL with query string attached.
const buildURL = (uri, params) => {
let queryParams = Object.keys(params).map(function(k) {
return encodeURIComponent(k) + '=' + encodeURIComponent(params[k])
}).join('&');
return uri + '?' + queryParams;
};
// Parses returned JSON object.
const parseStatistics = (result) => {
// My assumption here is that you are receiving a JSON string, which
// would need to be parsed into an object before being used.
let result = JSON.parse(result);
// Set base object
let namR = {};
// Iterate through themes array.
result.themes.forEach(function(element) {
// Find the object name for current theme.
let type = Object.keys(element)[0];
// Find count for current theme.
let count = element[type].individualValueVariable.count;
// Set count.
namR[type] = count;
});
// Log object
console.log(namR);
};
// Set up url info.
let params = {
city: $scope.strCity,
crimeType: $scope.type1,
years: $scope.type,
month: $scope.type2
};
let baseURL = "http://152.144.218.70:8080/USACrime/api/crimeAPI";
// Execute request.
$http.get(buildURL(baseURL, params)).success(parseStatistics(response));
Related
I'm working on a side project of a currency converter. I've made an API Call and this is all the data it sent me (this varies depending on the selected currencies so USD_GBP could be CAD_JPY):
{
"query": {
"count": 1
},
"results": {
"USD_GBP": {
"id": "USD_GBP",
"val": 0.733695,
"to": "GBP",
"fr": "USD"
}
}
}
In my express code I've set up the HTTPS Module:
https.get(url, function(response) {
response.on("data", function(data) {
const currencyData = JSON.parse(data);
const exchangeRate = currencyData.results.USD_GBP.val;
});
});
});
The problem you can probably see is that since the currency to convert from and convert to are always changing the constant exchangeRate doesn't work for any scenario besides converting from USD to GBP. So I'm wondering how to make that work for every combination that I throw at it. Above my HTTPS get request I already made a variable (const combine = firstCurrency + "_" + secondCurrency;) that combines the selections. I tried concatenating it to the exchangeRate variable, but it gave me an error that it can't find the value of undefined.
JavaScript objects allow you to use bracket notation for dynamic variables names.
var obj = { bar: 'baz'; }
var foo = 'bar';
obj.foo ; // This is invalid, as it looks for the "foo" property
obj[foo]; // This is valid, as it looks for the "bar" property we want
Since you mentioned you have a variable named combine already, you should be able to use bracket notation on the results:
const exchangeRate = currencyData.results[combine].val;
Here's a quick little snippet:
var firstCurrency = 'USD';
var secondCurrency = 'GBP';
const combine = firstCurrency + "_" + secondCurrency;
var response = `{
"query": {
"count": 1
},
"results": {
"USD_GBP": {
"id": "USD_GBP",
"val": 0.733695,
"to": "GBP",
"fr": "USD"
}
}
}`;
const currencyData = JSON.parse(response);
const exchangeRate = currencyData.results[combine].val;
console.log( exchangeRate );
If you didn't have the combine variable, you could always use Object.keys() to get the keys from the result and use that, but it's arguably uglier (especially since you already know the key):
const exchangeRate = currencyData.results[Object.keys(currencyData.results)[0]].val;
Instead of currencyData.results.USD_GBP.val, use currencyData.results['USD_GBP'].val
You can even use a variable as well. :
currencies = ['USD_GBP', 'EUR_USD']
currenceis.forEach(currency => {
currencyData.results[currency].val
}
Changed Example:
https.get(url, function(response) {
response.on("data", function(data) {
const currencyData = JSON.parse(data);
const exchangeRate = currencyData.results['USD_GBP'].val;
});
});
});
You can use the backtick syntax.
let firstCurrency = "USD";
let secondCurrency = "GBP";
const currencyData = {
"query": {
"count": 1
},
"results": {
"USD_GBP": {
"id": "USD_GBP",
"val": 0.733695,
"to": "GBP",
"fr": "USD"
}
}
};
const exchangeRate = currencyData.results[`${firstCurrency}_${secondCurrency}`].val;
console.log(exchangeRate);
Hi I'm new to React and nodejs. I get from the user his preferences for certain categories in the json code for example:
{
"sport" : {
"tennis": "5",
"running": "4",
"swimming": "5"
},
"study" : {
"history" : "0"
}
}
I want for each preference to create its own field in the "userPreferences" object.
This is the code I wrote down but I can not see what the error is here
exports.reduceUserPreferences = (data) => {
let userPreferences = {};
data.forEach(category => {
category.forEach(preference => {
category_preference_name = category.string + "_" + preference.string;
if (!isEmpty(preference.trim())) userPreferences.category_preference_name = preference;
});
});
//if (!isEmpty(data.tennis.trim())) userPreferences.sport_tennis = data.tennis;
//if (!isEmpty(data.swimming.trim())) userPreferences.sport_swimming = data.swimming;
//if (!isEmpty(data.running.trim())) userPreferences.sport_running = data.running;
//if (!isEmpty(data.history.trim())) userPreferences.study_history = data.history;
return userPreferences;
};
I want the "" object to have fields of all preferences along with the category to which they belong.
I can not understand what I am doing wrong, I linger on this code for several hours.
add example
I have another function similar to this function, the input is similar and the output is similar.
For example input:
{
"bio": "hello there",
"website": "",
"location": "los angles"
}
Example function:
exports.reduceUserDetails = (data) => {
let userDetails = {};
if (!isEmpty(data.bio.trim())) userDetails.bio = data.bio;
if (!isEmpty(data.website.trim())) {
// https://website.com
if (data.website.trim().substring(0, 4) !== 'http') {
userDetails.website = `http://${data.website.trim()}`;
} else userDetails.website = data.website;
}
if (!isEmpty(data.location.trim())) userDetails.location = data.location;
return userDetails;
};
The output will be:
An object with the attribute of all preferences along with their value.
I was looking for examples with a nested loop, I could not find.
There are a couple of things you need to fix in your code.
First, when using a variable name as the key to extract from an object, user obj[varName], not obj.varName.
(read more here: Dynamically access object property using variable)
Also, you're trying to loop an Object, not an array. To loop through the keys, use Object.keys()
Combining these two things you get the desired result, as you can see in this snippet. Also, for future questions, I highly recommend you make a snippet yourself.
const jsonOriginal = {
"sport" : {
"tennis": "5",
"running": "4",
"swimming": "5"
},
"study" : {
"history" : "0"
}
}
const reduceUserPreferences = (data) => {
let userPreferences = {};
Object.keys(data).forEach(category => {
Object.keys(data[category]).forEach(preference => {
category_preference_name = category + "_" + preference;
const preferenceValue = data[category][preference].trim();
if (preferenceValue !== '') userPreferences[category_preference_name] = preferenceValue;
});
});
return userPreferences;
};
console.log(reduceUserPreferences(jsonOriginal))
So I am pretty new when it comes to Javascript and it is as simple as read a json list with a value of:
{
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
What I would like to do is to have both the URL and the amount of numbers etc
"https://testing.com/en/p/-12332423/" and "999"
and I would like to for loop so it runs each "site" one by one so the first loop should be
"https://testing.com/en/p/-12332423/" and "999"
second loop should be:
"https://testing.com/en/p/-123456/" and "123"
and so on depending on whats inside the json basically.
So my question is how am I able to loop it so I can use those values for each loop?
As Adam Orlov pointed out in the coment, Object.entries() can be very useful here.
const URLobj = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
};
URLobj.URL.forEach(ob => {
console.log('ob', ob);
const entries = Object.entries(ob)[0]; // 0 just means the first key-value pair, but because each object has only one we can just use the first one
const url = entries[0];
const number = entries[1];
console.log('url', url);
console.log('number', number);
})
You mean something like this using Object.entries
const data = {
"URL": [
{"https://testing.com/en/p/-12332423/": "999"},
{"https://testing.com/en/p/-123456/": "123"},
{"https://testing.com/en/p/-456436346/": "422"}
]
}
data.URL.forEach(obj => { // loop
const [url, num] = Object.entries(obj)[0]; // grab the key and value from each entry - note the [0]
console.log("Url",url,"Number", num); // do something with them
})
let's call your object o1 for simplicity. So you can really go to town with this link - https://zellwk.com/blog/looping-through-js-objects/
or you can just use this code :
for(var i = 0; i < o1.URL.length; i++) {
//each entry
var site = Object.keys(URL[i]) [0];
var value = Object.values(URL[i]) [0];
// ... do whatever
}
don't forget each member of the array is an object (key : value) in its own right
You can extract the keys and their values into another object array using map
Then use the for loop on the newly created array. You can use this method on any object to separate their keys and values into another object array.
const data = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
var extracted = data.URL.map(e => ({
url: Object.keys(e)[0],
number: Object.values(e)[0]
}))
extracted.forEach((e) => console.log(e))
I am trying to use MAP into node.js program and I am getting final result however its in array but I need in map. I have write some code to use map but its not working as expected.
Please find below program
function CreateProduceMVPRateAsset(data, callback) {
var ProducePRICE = {};
var MVPPRICE = [];
var MVPPRICE_BS = {};
var MVPPRICE_LB = {};
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
console.log('Data', data);
console.log('Username', data.username);
var PRODUCENAME = data.PRODUCE;
var COUNTRY = data.COUNTRY;
var STATE = data.STATE;
var MVPRATES = data.MVPRATES;
console.log('MVPRATERATE', MVPRATES);
// here I need help
const MVPRATE = new Map(MVPRATES);
for (const [k, v] of MVPRATE.entries()) {
console.log('Inside map', k, v);
MVPPRICE = v.RATE; // should go in MVPPRICE
var Value = MVPPRICE[0].value; // want to get first element value from MVPPRICE array
console.log('Value', Value);
var value_lb = Value / 40;
console.log('value_lb', value_lb);
value_lb = Number(value_lb.toFixed(4));
console.log('If the value of BS provided controller come here');
MVPPRICE_LB.Value = value_lb;
MVPPRICE_LB.QuantityUnit = 'LB';
MVPPRICE_LB.uidisplay = false;
MVPPRICE_LB.CurrencyUnit = 'USD';
MVPPRICE.push(MVPPRICE_LB);
ProducePRICE.MVPPRICE = MVPPRICE;
ProducePRICE.PRODUCENAME = PRODUCENAME;
ProducePRICE.STATE = STATE;
ProducePRICE.COUNTRY = COUNTRY;
console.log('ProducePRICE', ProducePRICE); // whatever result getting it should be map however getting in array.
}
}
JSON structure which I am sending using postman
{
"username": "admin2",
"PRODUCE": "Apple",
"STATE": "MI",
"COUNTRY": "US",
"MVPRATES": {
"fuji": {
"VARIETY": "fuji",
"RATE": [
{
"UNIT": "Bussel",
"CURRENCY": "USD",
"VALUE": 10.25,
"UIDISPLAY": true
}
]
},
"gala": {
"VARIETY": "gala",
"RATE": [
{
"UNIT": "Bussel",
"CURRENCY": "USD",
"VALUE": 10.25,
"UIDISPLAY": true
}
]
}
}
}
Output which I am getting:
#SudhakarRS is right, you're getting your MAP back, you're just getting your values in an array for MVPRATE, and it almost looks like that was your intention, seeing you push here:
MVPPRICE.push(MVPPRICE_LB);
I mentioned in the comments, but I think what's happening is the Map doesn't apply recursively, so when it sees MVPPRICE, it's treating your value array, as the value instead of part of the map.
I think what you're trying to do can be solved by this:
MVPPRICE.concat(MVPPRICE_LB);
ProducePRICE.MVPPRICE = new Map(MVPPRICE)
I got the following problem,
I need to iterate through a big Json object ( child nodes consist of array's, strings and objects with at least 4-5 layers of depth in terms of nested properties ).
In some parts across the big Json file there is a specific object structure, it has a property named "erpCode". I need to scan the Json and find all the objects with that property, take the value use that code to ask a different API for details and once I get the details insert them into the object with the current 'erpCode'.
Just to clarify, in my case the parent node property name in the Json always equals the value in 'typeSysname' field which located on the same 'level' as the erpCode property.
A simple example :
{
"cars": [
{
"name": "X222",
"carType": {
"erpCode": "skoda",
"value": null,
"typeSysName": "carType"
}
}
],
"model": {
"year": 1999,
"details": {
"erpCode": "112"
"value": null,
"typeSysName": "details"
}
}
}
In this example I need to find 2 properties get the values skoda and 112 out of them and get the value and description data from a different API and set it into this Json in the right location.
P.S. Any chance there is a good npm package which can help me with that?
Edit:
I got a solution in C# from a few months ago which runs in a generic way on the Json and handles the complexity of the structure in a generic way.
But I now need to convert this into Javascript and I am a bit lost.
public static string TranslateDocErpCodes(string jsonString, string topRetailerSysName)
{
try
{
var doc = JObject.Parse(jsonString);
var erpCodeList = doc.SelectTokens("$..erpCode").ToList();
foreach (var erpCodeJToken in erpCodeList)
{
var value = erpCodeJToken?.Value<string>();
var erpCodeParent = erpCodeJToken?.Parent.Parent;
var erpCodeProperty = erpCodeParent?.Path.Split(".").Last();
var result =
_dataService.GetLovFromErpCode(topRetailerSysName, erpCodeProperty, value);
if (result == null)//reset lov obj
{
if (erpCodeParent?.Parent is JProperty prop)
prop.Value = JObject.FromObject(new LovObject { ErpCode = value });
}
else//set lov obj
{
result.ErpCode = value;
if (erpCodeParent?.Parent is JProperty prop)
prop.Value = JObject.FromObject(result);
}
}
return JsonConvert.SerializeObject(doc);
}
catch (Exception e)
{
throw new Exception("ErpConvert.TranslateDocErpCodes() : " + e);
}
}
mb something like;
function processObject(jsonData) {
for (prop in jsonData) {
if (jsonData.hasOwnProperty(prop)) {
// We get our prop
if (prop === 'code') {
let codeValue = jsonData[prop]
doSomeAsync(codeValue)
.then(response => {
jsonData[prop] = response;
})
}
let curValue = jsonData[prop];
if (Array.isArray(curValue)) {
// Loop through the array, if array element is an object, call processObject recursively.
processArray(curValue);
} else if (typeof curValue === 'object') {
processObject(curValue);
}
}
}
}
I took the answer from Aravindh as a starting point and managed to reach what seems to be a complete solution.
I will share it here,
async function convertErpCodes(jsonData, orgName, parentPropertyName){
for (let prop in jsonData) {
if (jsonData.hasOwnProperty(prop)) {
if (prop === 'erpCode') {
const erpCodeValue = jsonData[prop]
const req = {"query": {"erpCode": erpCodeValue, "orgName": orgName, "typeSysName": parentPropertyName}};
const result = await viewLookupErpService.findOne(req);
if(result)
return result;
}
const curValue = jsonData[prop];
if (Array.isArray(curValue)) {
for(let i in curValue){
const res = await convertErpCodes(curValue[i], orgName, prop);
}
} else if (curValue && typeof curValue === 'object') {
const response = await convertErpCodes(curValue, orgName, prop);
if(response){
jsonData[prop] = response;
}
}
}
}
}
P.S.
I set up the values only if I get a response from the third party API ( this is the reason for the result and response logic in the recursion.
I'd use object-scan and lodash.set in combination
// const objectScan = require('object-scan');
// const lodash = require('lodash');
const stats = { cars: [{ name: 'X222', carType: { erpCode: 'skoda', value: null, typeSysName: 'carType' } }], model: { year: 1999, details: { erpCode: '112', value: null, typeSysName: 'details' } } };
const entries = objectScan(['**.erpCode'], { rtn: 'entry' })(stats);
console.log(entries);
// => [ [ [ 'model', 'details', 'erpCode' ], '112' ], [ [ 'cars', 0, 'carType', 'erpCode' ], 'skoda' ] ]
// where you would query the external api and place results in entries
entries[0][1] = 'foo';
entries[1][1] = 'bar';
entries.forEach(([k, v]) => lodash.set(stats, k, v));
console.log(stats);
// => { cars: [ { name: 'X222', carType: { erpCode: 'bar', value: null, typeSysName: 'carType' } } ], model: { year: 1999, details: { erpCode: 'foo', value: null, typeSysName: 'details' } } }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
<script src="https://bundle.run/lodash#4.17.20"></script>
Disclaimer: I'm the author of object-scan