Load JSON file into JavaScript variable - javascript

So, I need to put the following code into a JSON file and load it into a separate JavaScript file:
var allQuestions = [{
question: "What is Elvis Presley's middle name?",
choices: ["David", "Aaron", "Eric", "Jack"],
correctAnswer: 1
}, {
question: "Who is the singer of the Counting Crows?",
choices: ["Adam Duritz", "John Adams", "Eric Johnson", "Jack Black"],
correctAnswer: 0
}, {
question: "Who is the Queen of Soul?",
choices: ["Mariah Carey", "Whitney Houston", "Aretha Franklin", "Beyonce"],
correctAnswer: 2
}, {
question: "Which famous group was once known as The Quarrymen?",
choices: ["The Beatles", "The Birds", "The Who", "Led Zeppelin"],
correctAnswer: 0
}];
In other words, the contents of allQuestions need to go in a JSON file and then loaded into the allQuestions variable in a separate JavaScript file. What would the JSON file look like and how would I load it into the allQuestions variable?

Try using JSON.stringify() , $.getJSON()
What would the JSON file look like
"[
{
"question": "What is Elvis Presley's middle name?",
"choices": [
"David",
"Aaron",
"Eric",
"Jack"
],
"correctAnswer": 1
},
{
"question": "Who is the singer of the Counting Crows?",
"choices": [
"Adam Duritz",
"John Adams",
"Eric Johnson",
"Jack Black"
],
"correctAnswer": 0
},
{
"question": "Who is the Queen of Soul?",
"choices": [
"Mariah Carey",
"Whitney Houston",
"Aretha Franklin",
"Beyonce"
],
"correctAnswer": 2
},
{
"question": "Which famous group was once known as The Quarrymen?",
"choices": [
"The Beatles",
"The Birds",
"The Who",
"Led Zeppelin"
],
"correctAnswer": 0
}
]"
how would I load it into the allQuestions variable?
$.getJSON("/path/to/json", function(data) {
var allQuestions = data;
})
jsfiddle https://jsfiddle.net/dydhgh65/1

You can use the ES6 fetch API, like so:
// return JSON data from any file path (asynchronous)
function getJSON(path) {
return fetch(path).then(response => response.json());
}
// load JSON data; then proceed
getJSON('/path/to/json').then(data => {
// assign allQuestions with data
allQuestions = data;
}
Here is how to do it using async and await.
async function getJSON(path, callback) {
return callback(await fetch(path).then(r => r.json()));
}
getJSON('/path/to/json', data => allQuestions = data);

Try this:
var myList;
$.getJSON('JsonData.json')
.done(function (data) {
myList = data;
});

Related

Javascript, filtering on object in comparison to array

I'm still learning and I had a question the other day filtering two arrays, which helped a lot for my understanding!
However now, I have a new issue as the complexity has grown a bit from being two simple arrays! Now instead, I have a array with multiple objects named animals which categorizes animals based whether they are housepets, insects or wild animals and each contains a object with their characteristics. Now I want to compare this on a simple array seen below.
Array with Object
let animals = [
{
"housePets" : [ { "name": "Cat", "food" : "Fish", "description": "Long tail, sharp claws" }, { "name": "Dog", "food" : "Biscuits", "description" : "Humans best friend" } ]
},
{
"wildAnimals" : [ { "name": "Giraffe", "food" : "Leafes", "description" : "A very long neck" }, { "name": "Lion", "food" : "Meat", "description" : "Featured in Lion King" } ]
},
{
"insects" : [ { "name": "Ladybug", "food" : "Leafes", "description" : "Red and black" }, { "name": "Spider", "food" : "Flies", "description" : "From the friendly neighbourhood" } ]
}]
Arr:
let animalsArr2 = [housePets]
I'm having a bit of trouble fully understanding on how to work with this JSON format in general. The biggest struggle for me is targeting the specific array like wildAnimals.
For example, one thing I want to do is filter the animals array based on what's inside animalsArr2 and pick a random one from the animalsarr that's not featured in animalsArr2 like "wildAnimals" and "Insects". I hope someone can give me some ideas on how to tackle this issue or if it can be tackled in a easier way.
You can use the .find() array method to return the list that you want. For example if you want to return the wild animals list:
let animals = [
{
"housePets" : [
{ "name": "Cat", "food" : "Fish", "description": "Long tail, sharp claws" },
{ "name": "Dog", "food" : "Biscuits", "description" : "Humans best friend" }
]
},
{
"wildAnimals" : [
{ "name": "Giraffe", "food" : "Leafes", "description" : "A very long neck" },
{ "name": "Lion", "food" : "Meat", "description" : "Featured in Lion King" }
]
},
{
"insects" : [
{ "name": "Ladybug", "food" : "Leafes", "description" : "Red and black" },
{ "name": "Spider", "food" : "Flies", "description" : "From the friendly neighbourhood" }
]
}
];
const wildAnimals = animals.find((item) => item.wildAnimals);
The code above basically checks which item in your array has a property called wildAnimals and returns that item. You can read more about this method Here.
Hope that helped!
I'm gonna suppose you are forced to use this format of storing data, but I feel like I have to let you know that this isn't the best way to store info like this (you will see that it is hard to work with it). Instead of having an array of objects, you could have an object of arrays like this:
let animals = {
"housePets": [{ "name": "Cat", "food": "Fish", "description": "Long tail, sharp claws" }, { "name": "Dog", "food": "Biscuits", "description": "Humans best friend" }],
"wildAnimals": [{ "name": "Giraffe", "food": "Leafes", "description": "A very long neck" }, { "name": "Lion", "food": "Meat", "description": "Featured in Lion King" }]
}
With this approach, getting all house animals would be as easy as animals.housePets.
Back to your issue tho. If you want to get all house animals from this, you will have to filter the array. To filter arrays, you have to give it a condition that the element has to pass to be stored. Here you can see that only the object with the house animals has a housePets property, so we can take advantage of that:
let house_animals = animals.filter(obj => obj.housePets)[0].housePets; // [{ "name": "Cat", "food": "Fish", "description": "Long tail, sharp claws" }, { "name": "Dog", "food": "Biscuits", "description": "Humans best friend" }]
What it does is that it takes all the objects that have the "housePets" property, takes the first one (I suppose there will always be only one) and reads the property, giving you the array of animals.
To find animals that are only in the housePets section and not in others, you can do this:
let house_animals = animals.filter(obj => obj.housePets)[0].housePets;
let wild_animals = animals.filter(obj => obj.wildAnimals)[0].wildAnimals;
let insects = animals.filter(obj => obj.insects)[0].insects;
let only_house = house_animals.filter(animal => !wild_animals.includes(animal) && !insects.includes(animal); // This checks if the animal is in the wild_animals or insects array. If it isn't, it keeps it.
You can also check this question out
Hope this helped :)
You can follow this code as a starting point. The complete example with updated data is below.
There are two key functions:
function _get(array, label): Take the array and get the names of the animals under the label category.
function _filterAndGet(mainList, filterList): Take the main list of animals, and filter out any animals that are in filter list. Then, pick a random animal from that filtered list.
Code
const animals = [
{
housePets : [{name: 'Cat', food : 'Fish', description: 'Long tail, sharp claws'}, {name: 'Dog', food : 'Biscuits', description : 'Humans best friend'}]
},
{
wildAnimals : [{name: 'Giraffe', food : 'Leafes', description : 'A very long neck'}, {name: 'Lion', food : 'Meat', description : 'Featured in Lion King'}, {name: 'Cat', food : 'Fish', description: 'Long tail, sharp claws'}, {name: 'Ladybug', food : 'Leafes', description : 'Red and black'}]
},
{
insects : [{name: 'Ladybug', food : 'Leafes', description : 'Red and black'}, {name: 'Spider', food : 'Flies', description : 'From the friendly neighbourhood'}]
}]
const wildAnimals = _get(animals, 'wildAnimals');
console.log(`Wild animals: ${JSON.stringify(wildAnimals)}`);
const housePetsAndInsects = _get(animals, 'housePets').concat(_get(animals, 'insects'));
console.log(`House Pets and Insects: ${housePetsAndInsects}`);
console.log(`Random wild animal not in housePets and insects: ${_filterAndGet(wildAnimals, housePetsAndInsects)}`);
function _filterAndGet(mainList, filterList) {
const filterSet = new Set(filterList);
const filteredMainList = mainList.filter(e => !filterSet.has(e));
const index = Math.floor(Math.random() * filteredMainList.length);
return filteredMainList[index];
}
function _get(array, label) {
const res = [];
for (const elem of array) {
for (const objKey of Object.keys(elem)) {
if (objKey === label) {
for (const item of elem[objKey]) {
res.push(item.name);
}
return res;
}
}
}
return res;
}
Example output:
Wild animals: ["Giraffe","Lion","Cat","Ladybug"]
House Pets and Insects: Cat,Dog,Ladybug,Spider
Random wild animal not in housePets and insects: Lion
You can try with this simple way by using Array.find() along with Array.some() methods.
Working Demo :
let animals = [{
"housePets": [
{ "name": "Cat", "food" : "Fish", "description": "Long tail, sharp claws" },
{ "name": "Dog", "food" : "Biscuits", "description" : "Humans best friend" }]
}, {
"wildAnimals": [
{ "name": "Giraffe", "food" : "Leafes", "description" : "A very long neck" },
{ "name": "Lion", "food" : "Meat", "description" : "Featured in Lion King" }]
}, {
"insects": [
{ "name": "Ladybug", "food" : "Leafes", "description" : "Red and black" },
{ "name": "Spider", "food" : "Flies", "description" : "From the friendly neighbourhood" }]
}];
let animalsArr2 = ['housePets'];
const res = animals.find((obj) => animalsArr2.some((elem) => Object.keys(obj).includes(elem)));
console.log(res);

how to edit json quickly

I make a table in Excel with 1000 questions and when convert it on JSON, I get:
[{
"QUESTION": "61771",
"ANSWERS": "2772718 ",
"CORRECT": "1,2,3,4"
},
{
"ANSWERS": "7271717"
},
{
"ANSWERS": "272727"
},
{
"ANSWERS": "6271717"
},
{
"QUESTION": "716171781",
"ANSWERS": "6171717",
"CORRECT": "1,2,3"
},
{
"ANSWERS": "7171616"
},
{
"ANSWERS": "287272"
},
]
But I need before "QUESTION" all "ANSWERS" connect to one "ANSWERS" and make a massive on "CORRECT", like this:
{
"QUESTION":"LALALLA",
"ANSWERS":["123214","123214","124214","12412414"]
"CORRECT":[1,2,3,4]
},
How can I quickly change/correct this JSON with js or other programming language?
Excel table link
In order to do this, you need a way to identify which answers are associated with which questions. Based on your sample data, this does not appear to be the case.
Is this what's needed?
code
let arr = [{
"QUESTION":"LALALLA",
"ANSWERS":"123214",
"CORRECT":"1,2,3,4",
},
{
"ANSWERS":"123214"
},
{
"ANSWERS":"124214"
},
{
"ANSWERS":"12412414"
}];
arr[0].CORRECT = arr[0].CORRECT.split(',').map((ele) => {
return parseInt(ele);
});
let answ = [];
arr.forEach((ele) => {
answ.push(ele.ANSWERS);
});
arr[0].ANSWERS = answ;
OUTPUT
console.log(arr[0])
{
"QUESTION": "LALALLA",
"ANSWERS": [
"123214",
"123214",
"124214",
"12412414"
],
"CORRECT": [
1,
2,
3,
4
]
}
Convert that into pandas in python
pandas.read_json(name) and try using transpose, melt, and some other functions pandas offer.

Is there a way to de-dupe a javascript array and combine values of the data?

I'm using an ajax request to grab some XML data which I then need to push into a chart in fusioncharts.
The XML data is formatted as [time taken], [work done], [which team done for], [who did it] (see below).
I'm iterating over the XML and then building the array using the code below:
//Time Recorded
if (columnidchecker == 7781) {
timearray.push($j(this).find('displayData').text());
temp1 = $j(this).find('displayData').text();
}
//Type of Activity
if (columnidchecker == 7782) {
activityarray.push($j(this).find('displayData').text());
temp2 = $j(this).find('displayData').text();
}
//Team Done For
if (columnidchecker == 7783) {
subjectarray.push($j(this).find('displayData').text());
temp3 = $j(this).find('displayData').text();
}
//Name
if (columnidchecker == 7777) {
internalclientarray.push($j(this).find('displayData').text());
temp4 = $j(this).find('userDisplayName').text();
}
});
//PUSH INTO A NEW ARRAY WHICH CAN THEN BE SORTED AND DE-DUPED WITH TIME COMBINED AGAINST ACTIVITY / TEAM.
objectarray.push([temp1, temp2, temp3, temp4]);
This builds an array of entries from the XML which basically outputs to something which looks like this:
0: (4) ["1.50", "Ad-hoc queries or calls", "Team 1", "James"]
1: (4) ["2.50", "Ad-hoc queries or calls", "Team 1", "James"]
2: (4) ["1.00", "Advice", "Team 2", "James"]
3: (4) ["3.50", "Meeting (External 3rd Party)", "Team 1", "James"]
4: (4) ["1.20", "Administration", Team 2", "James"]
5: (4) ["5.50", "Advice", "Team 1", "John"]
I'm trying to build a chart in fusioncharts which needs the format as shown below (ignore foot stuffs - it's taken straight from the fusioncharts help pages!).
{
"chart": {
"theme": "fusion",
"caption": "Revenue split by product category",
"subCaption": "For current year",
"xAxisname": "Quarter",
"yAxisName": "Revenues (In USD)",
"showSum": "1",
"numberPrefix": "$"
},
"categories": [
{
"category": [
{
"label": "Q1"
},
{
"label": "Q2"
},
{
"label": "Q3"
},
{
"label": "Q4"
}
]
}
],
"dataset": [
{
"seriesname": "Food Products",
"data": [
{
"value": "11000"
},
{
"value": "15000"
},
{
"value": "13500"
},
{
"value": "15000"
}
]
},
{
"seriesname": "Non-Food Products",
"data": [
{
"value": "11400"
},
{
"value": "14800"
},
{
"value": "8300"
},
{
"value": "11800"
}
]
}
]
}
The problem i'm having is that I cannot work out how to take the array of data with times, activity, team, name and push them into categories.
I think the first step is to create a new array of names which can be pushed into the "Category" data field in fusioncharts.
I then need a way in which to take the times being recorded against each activity and for each team and make sure it's assigned to the right person within the stacked bar chart and combine the amount of time spent. (i.e. "James" spent a total of 4 hours doing "Ad Hoc Queries and Calls" for Team 1 but this is split across two time entries so I need a way in which to combine them into one.)
Any help on this would be massively appreciated.
I can de-dupe the names to create a new array by using the following code:
namesarray.push(temp4);
uniq = [...new Set(namesarray)];
but after that it starts getting pretty complicated.
Maybe this can help you along the way. It's probably not exactly in the form you want it, but it demonstrates how you could break the problem down into smaller parts.
Pseudo-code:
get the unique names.
get the unique "task" names (for lack of a
better word)
for each unique person name:
3.1. get the data rows for that person
3.2 for each of all unique tasks names:
find the person data rows matching the task name
sum the duration of those data rows
const testData = [
[
"1.50",
"Ad-hoc queries or calls",
"Team 1",
"James"
],
[
"2.50",
"Ad-hoc queries or calls",
"Team 1",
"James"
],
[
"1.00",
"Advice",
"Team 2",
"James"
],
[
"3.50",
"Meeting (External 3rd Party)",
"Team 1",
"James"
],
[
"1.20",
"Administration",
"Team 2",
"James"
],
[
"5.50",
"Advice",
"Team 1",
"John"
]
];
const columnIndexByName = {
TASK_DURATION: 0,
TASK_NAME: 1,
FOR_WHICH_TEAM: 2,
PERSON_DOING_TASK: 3
};
const sum = (acc, next) => acc + next;
const uniqueNames = [...new Set(testData.map(row => row[columnIndexByName.PERSON_DOING_TASK])) ];
const uniqueTaskNames = [...new Set(testData.map(row => row[columnIndexByName.TASK_NAME])) ];
let result = {};
uniqueNames.forEach(personName => {
const personDataRows = testData.filter(row => row[columnIndexByName.PERSON_DOING_TASK] === personName);
let taskDurationsByTaskName = {};
uniqueTaskNames.forEach(taskName => {
const taskRows = personDataRows.filter(row => row[columnIndexByName.TASK_NAME] === taskName);
const taskDurations = taskRows.map(row => Number.parseFloat( row[columnIndexByName.TASK_DURATION] ));
const taskTotalDuration = taskDurations.reduce(sum, 0);
taskDurationsByTaskName[taskName] = taskTotalDuration;
})
result[personName] = taskDurationsByTaskName;
})
const renderData = data => document.querySelector("#output").innerHTML = JSON.stringify(data, null, 2);
renderData(result);
<pre id="output"></pre>

Filter the JSON object and write the results in the local .json file

I've fetched an API and got a JSON object that I need to filter through and store in a new local json file.
the results get returned, but I can't figure out a way to filter through the json file (data) and correctly write it into the new newfile.json file.
.then(
json => {
const data = JSON.stringify(json)
const filtered = data.map( //some filter function )
fs.writeFile('src/data/newfile.json', filtered, 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
Here is the example of the json data I'm getting from the array of surveys.
{
"surveyId": 515315,
"reviewId": "34152",
"transactionInfo": {
"transactionRef": "1806001511991",
"transactionCity": "Plymouth",
"transactionState": "MN",
"transactionType": null,
"customerFirstName": "Kristine",
},
"serviceProviderInfo": {
"serviceProviderName": "Lobster",
"serviceProviderEmail": "lobster#bayeq.com",
"serviceProviderId": 43346,
"serviceProviderOfficeName": "Oakdale - 30152501",
"serviceProviderRegionName": "Minnesota - Chacich",
"serviceProviderOfficeId": 721581,
"serviceProviderRegionId": 151563
},
"review": {
"source": "encompass",
"rating": "5.0",
"summary": null,
"description": "He was fantastic ",
"agreedToShare": true,
"verifiedCustomer": true,
"retakeSurvey": false,
"surveyResponses": [
{
"question": "How would you rate the service and support you received?",
"type": "Numeric",
"answer": "5"
},
{
"question": "Please rate the level of advice and communication you received from [name].",
"type": "Numeric",
"answer": "5"
},
{
"question": "How likely are you to refer friends and family to [name]?",
"type": "Numeric",
"answer": "10"
},
{
"question": "How would you rate your overall experience?",
"type": "Experience",
"answer": "Great"
}
],
"reportedAbusive": false
},
"reviewStatus": "completed"
}
How do I filter through this and create a new JSON file with the structure like
{
"email": "foo#bar.com",
"rating": 4.56,
"testimonials": [{
"description": "Fugiat ut sed occaecat.",
"firstname": "Bob",
"city": "Bananatown",
"state": "TH"
}]
}
Here I used jquery
var datat = {
"surveyId": 515315,
"reviewId": "34152",
"transactionInfo": {
"transactionRef": "1806001511991",
"transactionCity": "Plymouth",
"transactionState": "MN",
"transactionType": null,
"customerFirstName": "Kristine",
},
"serviceProviderInfo": {
"serviceProviderName": "Lobster",
"serviceProviderEmail": "lobster#bayeq.com",
"serviceProviderId": 43346,
"serviceProviderOfficeName": "Oakdale - 30152501",
"serviceProviderRegionName": "Minnesota - Chacich",
"serviceProviderOfficeId": 721581,
"serviceProviderRegionId": 151563
},
"review": {
"source": "encompass",
"rating": "5.0",
"summary": null,
"description": "He was fantastic ",
"agreedToShare": true,
"verifiedCustomer": true,
"retakeSurvey": false,
"surveyResponses": [
{
"question": "How would you rate the service and support you received?",
"type": "Numeric",
"answer": "5"
},
{
"question": "Please rate the level of advice and communication you received from [name].",
"type": "Numeric",
"answer": "5"
},
{
"question": "How likely are you to refer friends and family to [name]?",
"type": "Numeric",
"answer": "10"
},
{
"question": "How would you rate your overall experience?",
"type": "Experience",
"answer": "Great"
}
],
"reportedAbusive": false
},
"reviewStatus": "completed"
};
datat.review.surveyResponses = datat.review.surveyResponses.filter(function (a) {
return a.answer === "10";
});
var sd = datat.review.surveyResponses[0].question;
alert(sd);
I'm making some guesses here. As has been pointed out, there are so many discrepancies between the sample input and sample output that readers don't have confidence in the mapping inferences that are available. The correlations I've relied upon are inconsistent with the structure of the sample output, but these are the only options that are even plausible.
Also, I think you probably don't want to stringify the incoming data. You want it to be an object, so you can directly address the data; if the data is coming in as a string, you need to parse it into an object with JSON.parse
Here's something that might work. I've chained .then calls to make it easier to insert new steps and reorder them if necessary. I've omitted any error handling, but if you're parsing strings that you receive from the internet, you'll want to have something that can handle the error that will be thrown when the input string isn't valid JSON.
.then(string => JSON.parse(string)) // only needed if your earlier promise returns a string
.then(json => ({
email: json.serviceProviderInfo.serviceProviderEmail,
rating: json.review.rating,
testimonials: [{
description: json.review.description,
firstname: json.transactionInfo.customerFirstName,
city: json.transactionInfo.transactionCity,
state: json.transactionInfo.transactionState
}]
}))
.then(summary => {
return fs.writeFile('src/data/newfile.json', JSON.stringify(summary), 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
return true
})
})

How can get only key values from the join() values in javascript?

const myQuestions = [
{
level:"Level 1",
questionNo: 1,
sentence: "Her uncles are army officers.",
question: "Q . Which words are about people? ",
answers: {
"1": "a. uncles / officers",
"2": "b. her/are",
"3": "c. in/the"
},
correctAnswer: "1",
topic: "Noun",
description: "plural nouns"
},
{
level:"Level 1",
questionNo: 2,
sentence: "He dropped the glass and it broke into many pieces.",
question: "Q . Which word stands for 'the glass'?",
answers: {
"1": "a. he",
"2": "b. it",
"3": "c. into"
},
correctAnswer: "2",
topic: "Pronoun",
description: "pronoun 'it' and what it has already referred to"
},
....
]
This is my JSON. Here my Html5 codes below
<div class="answers"> ${answers.join("")} </div>
Now we got key and values also like this.
1: a. uncles / officers
But we want only values. Anybody can solve this bug?
You can use Object.values() for this:
${Object.values(answers).join("")}
const myQuestions = [{
level: "Level 1",
questionNo: 1,
sentence: "Her uncles are army officers.",
question: "Q . Which words are about people? ",
answers: {
"1": "a. uncles / officers",
"2": "b. her/are",
"3": "c. in/the"
},
correctAnswer: "1",
topic: "Noun",
description: "plural nouns"
}];
console.log(Object.values(myQuestions[0].answers).join(', '));
When you do:
answers.join("")
then the join method is applied to the entire answers object, and it will concatenate both its keys and values.
In order to feed only the values to join, do:
Object.values(answers).join("")
More specifically:
var answers = myQuestions[0].answers;
console.log(Object.values(answers).join(""));
(as shown in this codepen).
const myQuestions = [{
level: "Level 1",
questionNo: 1,
sentence: "Her uncles are army officers.",
question: "Q . Which words are about people? ",
answers: {
"1": "a. uncles / officers",
"2": "b. her/are",
"3": "c. in/the"
},
correctAnswer: "1",
topic: "Noun",
description: "plural nouns"
}]
const ans = Object.values(myQuestions[0].answers)
console.log(ans)

Categories

Resources