JavaScript: Parsing a JSON object with multiple levels - javascript

I have a JSON file with the following format:
{
"Afghanistan": [
{
"date": "2020-1-22",
"confirmed": 0,
"deaths": 0,
"recovered": 0
},
{
"date": "2020-1-23",
"confirmed": 0,
"deaths": 0,
"recovered": 0
},
...
],
"Albania": [
{
"date": "2020-1-22",
"confirmed": 0,
"deaths": 0,
"recovered": 0
},
{
"date": "2020-1-23",
"confirmed": 0,
"deaths": 0,
"recovered": 0
},
...
],
...
}
My goal is to extract data in a way so as to get the date, confirmed, deaths and recovered of each country. The problem I am having is finding a way to do this for all countries as opposed to just one.
For instance, if I write the line data.Afghanistan[0].confirmed; //data is a variable i stored the JSON object in, to get info for Afghanistan, I would need to write the same line for Albania as well and for all other countries separately.
I know there a way I can do this for all counties in a more efficient way but I can't seem to find it. Can someone please help me out? Any help would be appreciated. Thanks

Use Object.keys(). For example, Object.keys(yourJSONObject) will return an array of your keys, i.e. ["Afghanistan", "Albania"]. You can use this to iterate over each key/value in your JSON.

I think this would work:
const countries = Object.keys(data);
const confirmedDeathsByCountry = countries.map(country => data[country][0].confirmed);

You can loop through the arrays inside each country in your JSON file like so:
for (var key in data) {
//key is the country ie. "Afghanistan"
var records = data[key]; //array of records
for (var index in records) {
var record = records[index]; //object with the properties
var date = record.date;
var confirmed = record.confirmed;
var deaths = record.deaths;
var recovered = record.recovered;
}
}

Related

How can i filter a attribute from object from array of values in javascript

I need help.
i need filter a json object like this...
data =
[
{
"Empresa": "PLANTA",
"Sucursal": "AEROPUERTO",
"Producto": "PIZZA",
"Categoria": "RAPIDA"
"Total": 84,
"FPago": "TERMINAL",
"SegCliente": "SIN SEGMENTO",
"Origen": "MOSTRADOR"
},
{
"Empresa": "RIVERA",
"Sucursal": "CIRCUITO",
"Producto": "PASTEL",
"Categoria": "BOCADILLOS",
"Total": 152,
"FPago": "INALAMBRICA",
"SegCliente": "SIN SEGMENTO",
"Origen": "MOSTRADOR"
}
,...
]
I get a array from filtres from Categoria like this ['BOCADILLOS','POSTRES'...]
and another to empresa like ['PLANTA',...]
I built these arrays dynamically
How can i filter data.Categoria with values in ['BOCADILLOS','POSTRES'...]
ty for help
You can use Array.filter
let categories = ['BOCADILLOS', 'POSTRES'];
let filtered = data.filter((item) => categories.includes(item.Categoria));

editing a JSON in JS and putting it in an array

so I have the following json.
{
"BTC": {
"available": 0.00024868,
"onOrder": 0,
"btcValue": 0.00024868,
"btcTotal": 0.00024868
},
"LTC": {
"available": 0,
"onOrder": 0,
"btcValue": 0,
"btcTotal": 0
},
"ETH": {
"available": 0,
"onOrder": 0,
"btcValue": 0,
"btcTotal": 0
},
"NEO": {
"available": 0,
"onOrder": 0,
"btcValue": 0,
"btcTotal": 0
},
"BNB": {
"available": 0.08943066,
"onOrder": 0,
"btcValue": 0.0004663808919,
"btcTotal": 0.0004663808919
}
}
I need to remove the items that don't have a value in the "available" field (such as NEO and ETH and set the result in an array. Then remove the onOrder and btcTotal fields.
such as:
BTC 0.00024868 0.00024868
BNB 0.8943066 0.0004663808919
I am writing my little project in JS on NodeJS as a little hobby project. But, so far all I am able to get right is listing the JSON in the console.
Something like this might work:
const json = `{"BTC":{"available":0.00024868,"onOrder":0,"btcValue":0.00024868,"btcTotal":0.00024868},"LTC":{"available":0,"onOrder":0,"btcValue":0,"btcTotal":0},"ETH":{"available":0,"onOrder":0,"btcValue":0,"btcTotal":0},"NEO":{"available":0,"onOrder":0,"btcValue":0,"btcTotal":0},"BNB":{"available":0.08943066,"onOrder":0,"btcValue":0.0004663808919,"btcTotal":0.0004663808919}}`;
const data = JSON.parse(json);
const processed = Object.entries(data)
.filter(([, { available }]) => available > 0)
.map(([asset, { available, btcValue }]) => {
return { asset, available, btcValue };
});
const asArray = processed.map(Object.values);
console.table(processed);
console.log(asArray);
Object.entries returns an array of key-value pairs. Since it's an array, you can:
call filter method to only keep items where available was greater than 0
call map method to transform the filtered array of key-value pairs into an array of objects (where each object has properties: asset, available, btcValue)
You can get rid of asArray if you want, if it's not useful. It's just to give you an idea of what's possible.

organize MongoDB document to manipulate the data better

I would need help making a data structure with mongodb.
I'm using JavaScript to manipulate data.
I would like to have a document structure of this type, but i'm not sure to do the right thing. I noticed that you tend to use the array also as a container of objects, and i also noticed that the mongodb update operators need a structure of this type. for example:
var mydoc = {
_id: ObjectId("5099803df3f4948bd2f98391"),
items:[ {"name": "name", "other": "other"},
{"name": "name", "other": "other"},
{"name": "name", "other": "other"}
]}
but organize data in this way do not like :) how i would like the document:
{
"_id": {
"$oid": "dfdsdsfdsff54sdf5ds"
},
"displayName": "name",
"userId": "h8566d9482gghffhtry565",
"info": {
"level": 1,
"currentExperience": 0,
"requiredExperience": 0,
"missingExperience": 0
},
"statistics": {
"total": {
"stat1": 0,
"stat2": 0,
"stat3": 0,
"stat4": 0
},
"best": {
"distance": 0,
"stat1": 0,
"stat2": 0,
"stat3": 0,
"stat4": 0
},
"game": {
"one": 0,
"two": 0,
"three": 0,
"stat4": 0
}
},
"inventory": {
"item1": {
"property1": 0,
"property2": 0,
"property3": 0,
"property4": 0,
"level": {
"level": 1,
"currentExperience": 0,
"requiredExperience": 0,
"missingExperience": 0
},
"skins": [
"skin1",
"skin2",
"skin3"
]
},
"item2": {
"property1": 0,
"property2": 0,
"property3": 0,
"property4": 0,
"level": {
"level": 1,
"currentExperience": 0,
"requiredExperience": 0,
"missingExperience": 0
},
"skins": [
"skin1",
"skin2",
"skin3"
]
}
},
"notifications": {},
"rewards": {}
}
Now i explain what the problems im having.
now if i have to change, for example, a property of a specific item that is inside inventory, i take the object "inventory" -> i look for the item i need and then i modify the property.
at the end of this, using an update operator "$set", i replace the "inventory" field.
This may be fine if you have very little data, but within that field there will be hundreds of "sub-field" and this seems like a useless waste resources.
Unfortunately, using $inc operator, i can not pass in any way "the path" of the property that i want to change.
could you help me?
here is what i do now
var userDoc = myCollection("userData");
var userData = userDoc.findOne({"userId": userId}, {items: 1, _id: 0});
//Other code
userData.inventory[itemName][propertyName] = //other code;
userDoc.update({"userId": userId},{"$set": userData});
Thanks,
Regards
If you want to update an embedded document, you can access it using dot notation.
For above document, to update "property1" of "item1" inside "inventory":
db.inventory.update({"userId":"h8566d9482gghffhtry565"},{"$set":{"inventory.item1.property1":"1"}})
the problem is that the "path" is dynamic, I do not know which item will be modified. is the user decide which properties of the items change, I found this solution:
var inc = {$inc: {}};
inc.$inc['inventory.'+itemName+"."+statName] = 1; // itemName and statName are variables created by user
userDoc.update({"userId": userId}, inc);

Javascript nested array transformation

I'm trying to get my head around Javascript array functions. I have a nested array like this, where every row covers the same time period:
[{
"category": "fruit",
"variety": "apple",
"data": [{
"day": 1,
"units": 2
}, {"day": 2,
"units": 4
}]
},{
"category": "fruit",
"variety": "orange",
"data": [{
"day": 1,
"units": 3
}, {"day": 2,
"units": 5
}]
},{
"category": "veg",
"variety": "tomato",
"data": [{
"day": 1,
"units": 4
}, {"day": 2,
"units": 2
}]
}]
I would like to sum the units by day by category, to get an array like this:
[{
"category": "fruit",
"data": [{
"day": 1,
"units": 5
}, {"day": 2,
"units": 9
}]
},{
"category": "veg",
"data": [{
"day": 1,
"units": 4
}, {"day": 2,
"units": 2
}]
}]
I've been tackling this through long looping if statements, and making a bit of a hash of it. Can you see an elegant way to solve this?
Many thanks!
The solution is pretty obvious: Loop through the array, and store the data in a key-value pair. Then, loop through the has, and construct the resulting array using Array.prototype.map. Finally, if you want a nicely formatted JSON-string, use JSON.stringify(result, null, 4);, where 4 is the number of spaced for pretty formatting.
Demo: http://jsfiddle.net/jde6S/
var list = [ ... ];
var hash = {};
for (var i=0; i<list.length; i++) {
var obj = list[i];
// This part makes sure that hash looks like {fruit:[], veg: []}
var hashObjCat = hash[obj.category];
if (!hashObjCat) {
hashObjCat = hash[obj.category] = {};
}
// This part populates the hash hashObjCat with day-unit pairs
for (var j=0; j<obj.data.length; j++) {
var data = obj.data[j];
if (hashObjCat[data.day]) hashObjCat[data.day] += data.units;
else hashObjCat[data.day] = data.units;
}
}
// Now, we hash looks like {fruit: {1:5, 2:9} }
// Construct desired object
var result = Object.keys(hash).map(function(category) {
// Initial object
var obj = {category: category, data:[]};
var dayData = Object.keys(hash[category]);
// This part adds day+units dicts to the data array
for (var i=0; i<dayData.length; i++) {
var day = dayData[i];
var units = hash[category][day];
obj.data.push({day: day, units: units});
}
return obj;
});
// Test:
console.log(JSON.stringify(result, null, 4));
reduce the array to an object (See #RobW's answer on how to do that with loops):
var data = [...] // your input
// Iterate the data with reduce...
var sumsbycategory = data.reduce(function(map, fruit) {
var cat = fruit.category;
// set an property to an object, iterating the days array...
map[cat] = fruit.data.reduce(function(sums, day) {
var d = day.day;
// set or update the units for this day
sums[d] = (sums[d] || 0) + day.units;
return sums; // into the next iteration
}, map[cat] || {}) // ...passing in the already existing map for this cat or a new one
return map; // into the next iteration
}, {}); // ...passing in an empty object
Now we have the following format:
{"fruit":{"1":5,"2":9},"veg":{"1":4,"2":2}}
...which I think is much easier to handle, but lets build your array:
var result = []; // init array
for (var cat in sumsbycategory) { // loop over categories
var data = []; // init array
// add category object:
result.push({category:cat, data:data});
for (var day in sumsbycategory[cat]) // loop over days in category
// add day object
data.push({day:day, units:sumsbycategory[cat][day]});
}
But, wait! An object has no order, and it could happen that day2 comes before days1 in the result array (which might break your appplication?) So, you could use map on the keys of that object which also can be sorted before, to generate the array in one clean-looking expression:
var result = Object.keys(sumsbycategory).map(function(cat) {
return {
category: cat,
data: Object.keys(sumsbycategory[cat])
.sort(function numbercompare(a,b){ return a-b; })
.map(function(day) {
return {
day: day,
units: sumsbycategory[cat][day]
};
})
};
});
result:
[{
"category": "fruit",
"data": [{"day":"1","units":5},{"day":"2","units":9}]
},{
"category": "veg",
"data": [{"day":"1","units":4},{"day":"2","units":2}]
}]
(Demo at jsfiddle.net)
If you're willing to grab some external code and use it to essentially re-index your structure you could probably do something. I know the old dojo data api was a mess to work with, but could allow something like what you seem to be asking.
Personally I'd stick with loops, just keep your variable names readable. Also remember the object literals can be addressed as either an array/hash syntax x[y] or dot syntax x.y

Parsing JSON with jQuery, retrieving two variables.

I have a online JSON file that looks something like this:
[
{
"j": 0,
"i": 0,
"DepartureTime": "\/Date(1331667480000+0100)\/",
"ArrivalTime": "\/Date(1331668860000+0100)\/",
"Remarks": [],
"TravelStages": [
{
"ID": 0,
"DepartureStop": {
"WalkingDistance": 0,
"ArrivalTime": null,
"AlightingAllowed": false,
"DepartureTime": null,
"BoardingAllowed": false,
"RealTimeStop": true,
"Rank": 0,
"Lines": null,
"StopPoints": [
{
"ID": 1,
"Name": "1",
"X": 608127,
"Y": 6645778
}
],
"Zone": "1",
"X": 608133,
"Y": 6645768,
"ID": 2300500,
"Name": "Visperud (i Solheimvn)",
"District": "Lørenskog",
"Type": 0,
"Stops": [],
"ShortName": "VIS"
}]
What I want is the grab out the DepartureTime and ArrivalTime, I've seen some examples on how to parse the flickr JSON. But I can't figure out how I can parse this. I also want to store the departureTime and arrivalTime in two separate variables since the content of this two is a time measured in milliseconds since 1970. Can somebody give me a hint on how a can do this, am totally new to Javascript/JSON
Do you have jQuery in your project? If so, you can easily parse the JSON string like this
var obj = $.parseJSON(theJsonText);
alert(obj.DepartureTime);
If not, I suggest including the JSON library (link) and using that.
You can try something like this, assuming that your json file is in jsonfile.json
$.getJSON('jsonfile.json', function(data){
alert("Departure Time: "+ data.DepartureTime);
alert("Arrival Time: "+ data.ArrivalTime);
});
http://api.jquery.com/jQuery.getJSON/
$.getJSON('http://your.domain.example/path/to/file.json', function(data) {
departure_time=data.DepartureTime;
arrival_time=data.ArrivalTime;
do_something_with(departure_time,arrival_time);
});
then do_something_with(str,str) would be called with the strings "\/Date(1331667480000+0100)\/" and "\/Date(1331668860000+0100)\/" (in your example).
you'll still have to convert the dates to numbers, e.g. by running:
parsed_date=new Date(parseInt(input_string.substr(7)));
//substr(7) cuts after "\/Date(", and parseInt ignores ")\/"
//but I don't know how it handles "+0100"
Thats an array containing objects, so you should be able to just set some vars equal to the properties of the first index. to use it like an object, it needs to be parsed.. so either eval(thatJson) or $.parseJSON(thatJson) and then iterate through it.
var responses = [
{
"j": 0,
"i": 0,
"DepartureTime": "\/Date(1331667480000+0100)\/",
"ArrivalTime": "\/Date(1331668860000+0100)\/",
"Remarks": [],
...
}];
var dep = responses[0].DepartureTime;
var arr = responses[0].ArrivalTime;
According to JSONLint.com, your string isn't valid JSON. That is, however, a different issue than what your question asks for.
Assuming a valid subset of your string
var a = '[{"j": 0,"i": 0,"DepartureTime": "/Date(1331667480000+0100)/", "ArrivalTime": "/Date(1331668860000+0100)/","Remarks": []}]';
var obj = $.parseJSON(a);
console.log(obj[0].ArrivalTime);​

Categories

Resources