Correct JSON format - javascript

Is this correct json format?
{
"count": {
"hbase": 66,
"java": 63,
"spring": 41,
"Sample": 39,
"minify": 36,
"TS-WS1": 28,
"jprofiler": 26,
"logging": 24,
"SCM": 24,
"csrfguard": 20,
"ldap": 19,
"hadoop": 18,
"jquery": 18,
"android": 17,
"TS-WS2": 17,
"myplace": 16,
"jvm": 16,
"daily": 15,
"oops": 15,
"node.js": 15,
"long": 15,
"css3": 13,
"html5": 13,
"jms": 13,
"ci": 11,
"node": 11,
"backlog": 11,
"jsf": 10,
"groovy": 10,
"outofmemory": 9,
"adf": 9,
"Exception": 9,
"guidelines": 9,
"abc": 9,
"liferay": 8,
"performance": 7,
"Groovy": 7,
"jenkin": 7,
"Hadoop": 6,
"Learning": 6,
"code": 6,
"design": 6,
"CTT4TL": 6,
"": 6,
"eclipse": 5,
"templates": 5,
"apache": 5,
"Node.JS": 5,
"analytics": 5,
"cap": 4,
"CSRFGuard": 4,
"corba": 4,
"pattern": 4,
"EST-WS1": 4,
"web": 4,
"formatter": 4,
"Minify": 4,
"guava": 3,
"oracle": 3,
"security": 3,
"checklists": 3,
"lda": 3,
"ana": 3,
"bi": 3,
"ctt4tl": 3,
"est-ws2": 3,
"exception": 3,
"EST-WS2": 3,
"oop": 3,
"how": 3,
"hibernate": 3,
"LDAP": 2,
"cxf": 2,
"Scala": 2,
"interceptor": 2,
"hudson": 2,
"jenkins": 2,
"sonar": 2,
"viva": 2,
"nfr": 2,
"java7": 2,
"CSS3": 2,
"jpa": 2,
"ppt": 2,
"Hudson": 2,
"template": 2,
"des-ws3": 2,
"Hadoop\/HBase": 1,
"secur": 1,
"csrf": 1,
"DB": 1,
"university": 1,
"abcd": 1,
"jsa": 1,
"LOGGING": 1,
"json": 1,
"rm": 1,
"TS-SCM": 1,
"nak": 1,
"fad": 1,
"presentation": 1,
"est-ws1": 1,
"terna": 1,
"lucene": 1,
"coding": 1,
"log4j": 1,
"JPA": 1,
"theme": 1,
"training": 1,
"secu": 1,
"build": 1,
"css": 1,
"project": 1,
"solr": 1,
"DES-WS": 1,
"intercep": 1,
"test": 1
},
"date": MonMay0612: 19: 48IST2013
}
I receive this JSON on one of my ajax call. And just after receiving it shows "parserror".
My code -
$.ajax({
type: "GET",
url: jsonURL + SEARCH_HISTORY_JSON + EXT_JSON,
dataType: "json",
contentType: "application/json",
async : false,
success: function(data) {
},
error: function(xhr, status, error) {
/* $("#tagCloud").html(getMessage(tagcloud.error));
$("#searchHistory").hide();*/
alert(status);
console.log(status);
}
});
Also please tell me how to access this data. Should I access it like data.data and data.count?

Parse error on line 121:
... }, "date": MonMay0612: 19: 48IS
---------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '['
http://jsonlint.com/
You need to put your date like this -
"date": "MonMay0612: 19: 48IST2013"

The problem is on the "date" field.
You should treat date fields as strings.
Also, I would recommend using UNIX time for that purpose, because it is easier to parse from javascript.
In the success function, you can access the "count" field like data.count.

http://jsonlint.com/
Parse error on line 121:
... }, "date": MonMay0612: 19: 48IS
---------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '['
A very easy way to lint your JSON.

Change your date format as following:
"date":"Mon May 06 12:19:48 IST 2013"
& follow the json online editor.i.e. chrome : http://jsoneditoronline.org/

The problem is on the date field.
Please pass date filed value with "MonMay0612: 19: 48IST2013"

Related

Sum of specific field in one array if condition is met

I have two arrays. I would like to get the sum of time_spent field if course_id is same in arr1 as well as if course_id matches the id field of arr2
let arr1 = [
{ instructor_id: 7, course_id: 19, lesson_id: 1, time_spent: 0 },
{ instructor_id: 7, course_id: 19, lesson_id: 2, time_spent: 0 },
{ instructor_id: 7, course_id: 19, lesson_id: 3, time_spent: 0 },
{ instructor_id: 7, course_id: 20, lesson_id: 4, time_spent: 80 },
{ instructor_id: 7, course_id: 20, lesson_id: 5, time_spent: 40 },
{ instructor_id: 8, course_id: 21, lesson_id: 6, time_spent: 0 },
];
let arr2 = [
{ id: 19, title: "Course 19", duration: 180 },
{ id: 20, title: "Course 20", duration: 120 },
];
// expected result
newArr = [
{ instructor_id: 7, course_id: 19, time_spent: 0 },
{ instructor_id: 7, course_id: 20, time_spent: 120 },
];
There are many ways to do this, and although you didn't fully specify what should happen with all the fields, there is a straightforward way to use Array reduce to perform a selective sum.
As a clever shortcut, you can multiply a value by a boolean to sum up only matching values by adding 0 for non-matching items. condition * value is equivalent to the ternary condition ? value : 0
const arr1 = [
{ instructor_id: 7, course_id: 19, lesson_id: 1, time_spent: 0 },
{ instructor_id: 7, course_id: 19, lesson_id: 2, time_spent: 0 },
{ instructor_id: 7, course_id: 19, lesson_id: 3, time_spent: 0 },
{ instructor_id: 7, course_id: 20, lesson_id: 4, time_spent: 80 },
{ instructor_id: 7, course_id: 20, lesson_id: 5, time_spent: 40 },
{ instructor_id: 8, course_id: 21, lesson_id: 6, time_spent: 0 },
];
const arr2 = [
{ id: 19, title: "Course 19", duration: 180 },
{ id: 20, title: "Course 20", duration: 120 },
];
const result = arr2.map(({ id }) => ({
course_id: id,
time_spent: arr1.reduce(
(prev, cur, index) => prev + (cur.course_id == id) * cur.time_spent
, 0)
}));
console.log(result);

why am i getting <1 empty item> when using mapping in JavaScript

im using JSON to return an array.
Json:
const data = [{
"week": 1,
"lost": 10,
"recovery_timespan": [{
"week": 2,
"count": 1
}, {
"week": 3,
"count": 0
}],
"netLost": 10,
"netReturned": 20
}, {
"week": 2,
"lost": 7,
"recovery_timespan": [{
"week": 3,
"count": 1
}, {
"week": 4,
"count": 3
}],
"netLost": 30,
"netReturned": 200
}, {
"week": 3,
"lost": 8,
"recovery_timespan": [{
"week": 4,
"count": 1
}],
"netLost": 50,
"netReturned": 40
}];
i need to get the data into a array with lost,counts of recovery_timespan,netLost,netReturned.
Expected Output:
[ [ 10, 1, 0, 10, 20 ],
[ 7, 1, 3, 30, 200 ],
[ 8, 1, 50, 40 ] ]
My approach:
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...recovery_timespan.map(({count}) => count),
,netLost,netReturned
]);
console.log(result);
and this return array with <1 empty item>:
[ [ 10, 1, 0, <1 empty item>, 10, 20 ],
[ 7, 1, 3, <1 empty item>, 30, 200 ],
[ 8, 1, <1 empty item>, 50, 40 ] ]
Wha is the issue here?
Why am i getting <1 empty item>
You have an extra comma:
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...recovery_timespan.map(({count}) => count),
here ---> ,netLost,netReturned
]);
Just remove it.
You have an additional , after the nested map:
const result = data.map(({lost, recovery_timespan,netLost,netReturned}) => [
lost,
...recovery_timespan.map(({count}) => count), // <--
,netLost,netReturned
//^--
]);
That creates a hole in the array. That's why you are seeing <1 empty item> in the output
console.log([1,,2])
const res = data.map((el) => [
el.lost,
...el.recovery_timespan.map((timespan) => timespan.count),
/* extra comma here --> */, el.netLost,
el.netReturned
])
[ [ 10, 1, 0, 10, 20 ], [ 7, 1, 3, 30, 200 ], [ 8, 1, 50, 40 ] ]
Not completly sure, but maybe try this.
...recovery_timespan.map(({count}) => count.count)

Hide or show two datasets with one click event of legend in chart.js

I want to show visualization of machines downtime for 2 shifts - day (12-hr) and night (12-hr) for 30 days. Thus, I use the stacked bar chart with groups and it looks good accept that I don't want to have the legends to show both shifts (day & night).
stacked bar chart with groups
<canvas id="myChart"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30",],
datasets: [{
label: 'Machine 1 - Day',
stack: 'Stack 0',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF4A4A',
},
{
label: 'Machine 1 - Night',
stack: 'Stack 1',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF4A4A',
},
{
label: 'Machine 2 - Day',
stack: 'Stack 0',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF9C2A',
},
{
label: 'Machine 2 - Night',
stack: 'Stack 1',
data: [12, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF9C2A',
},
]
},
options: {
plugins: {
legend: {
display: true
}
},
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
</script>
How do I combine the machine 1 or 2 for day & night shift in the legend and clicking machine 1 or 2 will hide both shifts (day & night)
stacked bar chart with groups edit Legend
I found the method below that might work for me.
https://www.chartjs.org/docs/3.1.0/configuration/legend.html#custom-on-click-actions
click handler of the first two datasets
How do I proceed for second two datasets of the click handler and so on accordingly.
<canvas id="myChart"></canvas>
<script>
var defaultLegendClickHandler = Chart.defaults.plugins.legend.onClick;
var newLegendClickHandler = function (e, legendItem, legend) {
var index = legendItem.datasetIndex;
if (index > 1) {
// Do the original logic
defaultLegendClickHandler(e, legendItem);
} else {
let ci = legend.chart;
[
ci.getDatasetMeta(0),
ci.getDatasetMeta(1)
].forEach(function (meta) {
meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
});
ci.update();
}
};
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30",],
datasets: [{
label: 'Machine 1 - Day',
stack: 'Stack 0',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF4A4A',
},
{
label: 'Machine 1 - Night',
stack: 'Stack 1',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF4A4A',
},
{
label: 'Machine 2 - Day',
stack: 'Stack 0',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF9C2A',
},
{
label: 'Machine 2 - Night',
stack: 'Stack 1',
data: [12, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF9C2A',
},
]
},
options: {
plugins: {
legend: {
onClick: newLegendClickHandler
}
},
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
</script>
First you need to define a legend.labels.generateLabels function that filter out undesired legend labels and changes the text of the remaining ones.
generateLabels: chart => chart.data.datasets.map((ds, i) => ({
text: ds.label.substring(0, ds.label.indexOf('-')),
datasetIndex: i,
fillStyle: chart.data.datasets[i].backgroundColor,
strokeStyle: chart.data.datasets[i].backgroundColor,
hidden: chart.getDatasetMeta(i).hidden
}))
.filter((ds, i) => i % 2),
Then you'll have to define a legend.onClick function that takes care of also showing/hiding the sibling dataset when the user clicks on a legend label.
onClick: (event, legendItem, legend) => {
let hidden = !legend.chart.getDatasetMeta(legendItem.datasetIndex).hidden;
(legendItem.datasetIndex == 1 ? [0, 1] : [2, 3])
.forEach(i => legend.chart.getDatasetMeta(i).hidden = hidden);
legend.chart.update();
}
For further details, see the Legend and API chapters of the Chart.js documentation.
Please take a look at your amended code and see how it works.
new Chart('chart', {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", ],
datasets: [{
label: 'Machine 1 - Day',
stack: 'Stack 0',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF4A4A',
},
{
label: 'Machine 1 - Night',
stack: 'Stack 1',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF4A4A',
},
{
label: 'Machine 2 - Day',
stack: 'Stack 0',
data: [5, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF9C2A',
},
{
label: 'Machine 2 - Night',
stack: 'Stack 1',
data: [12, 13, 5, 20, 4, 9, 28, 19, 21, 5, 13, 7, 21, 26, 10, 28, 19, 21, 30, 10, 27, 6, 12, 15, 4, 2, 13, 8, 29, 30],
backgroundColor: '#FF9C2A',
}
]
},
options: {
plugins: {
legend: {
labels: {
generateLabels: chart => chart.data.datasets.map((ds, i) => ({
text: ds.label.substring(0, ds.label.indexOf('-')),
datasetIndex: i,
fillStyle: chart.data.datasets[i].backgroundColor,
strokeStyle: chart.data.datasets[i].backgroundColor,
hidden: chart.getDatasetMeta(i).hidden
}))
.filter((ds, i) => i % 2),
},
onClick: (event, legendItem, legend) => {
let hidden = !legend.chart.getDatasetMeta(legendItem.datasetIndex).hidden;
(legendItem.datasetIndex == 1 ? [0, 1] : [2, 3])
.forEach(i => legend.chart.getDatasetMeta(i).hidden = hidden);
legend.chart.update();
}
}
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true
}
}
}
});
canvas {
max-height: 190px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
<canvas id="chart"></canvas>
Hey I got something like this working, but I am hiding everything with the same stack variable and hiding certain data series as well so I can hide them without having their legend items available for click:
I have a lot of series that have the same datasets (ie, failed numbers, retested numbers and dont want to show those labels)
// Get Data From Views and Add Custom onClick Listener
let tempData = { ...views[i].data };
if (
// Kill the onClick and add a much slower but grouping onClick, hide all with part number in stack
tempData &&
tempData.options &&
tempData.options.plugins &&
tempData.options.plugins.legend
)
tempData.options.plugins.legend.onClick = (e, legendItem) => {
// My labels always start with the part number and a space so I grab that.
const partName = legendItem.text.split(' ')[0];
const chart = Chart.getChart('temp-chart');
// Toggle the data set that was clicked on
const datasetIndex = legendItem.datasetIndex;
if (!chart.getDatasetMeta(datasetIndex).hidden) chart.hide(datasetIndex);
else chart.show(datasetIndex);
let j = 0;
// Iterate through all datasets, cap at 200 for safety
while (chart.getDatasetMeta(j).stack && j < 200) {
const datasetMeta = chart.getDatasetMeta(j);
const stack = datasetMeta.stack;
const datasetName = datasetMeta.label;
// I add a stack id to all my datasets and use that to determine what is 'grouped'
// I have a plugin that does not render any datasets which do not have a label
// If the stack group matches and the dataset does not have a label it will be hidden.
if (
stack === partName &&
(datasetName == null ||
datasetName === '' ||
datasetName === 'undefined')
) {
if (!chart.getDatasetMeta(j).hidden) chart.hide(j);
else chart.show(j);
}
j++;
}
};
new Chart('temp-chart', { ...tempData });
And the legend plugin to hide legend items with no label.
Chart.defaults.plugins.legend.labels.filter = (item) => {
return item.text != null;
};
Heres what I got - Pictures

Sorting array from Firebase fails

I'm trying to get an array of users sorted by the number of their likes. I am getting the user from a Firebase database, in case this changes things.
User example:
{
"likes": [
{
"createDate": {
"date": 22,
"day": 3,
"hours": 10,
"minutes": 33,
"month": 7,
"seconds": 25,
"time": 1534934005660,
"timezoneOffset": 0,
"year": 118
},
"creatorID": "1OA4U39rsPPXZblWG6nLHObB7gz1",
"firebaseKey": "-LKWBYQFbaO1Fs8_Rllc",
"workID": "-LK6-jxPZ0tCNW6c-GTI",
"id": "0"
},
{
"createDate": {
"date": 22,
"day": 3,
"hours": 13,
"minutes": 45,
"month": 7,
"seconds": 50,
"time": 1534938350990,
"timezoneOffset": -120,
"year": 118
},
"creatorID": "8Z7dd5L01FW0EbV0Wvu1KaXfmOx1",
"firebaseKey": "-LKWS7ZsUu2Khn0j7vLk",
"workID": "-LK5xZaui7IIcJcT22Rp",
"id": "1"
}
],
}
I was trying to use the sort method like this, but no luck.
var solversByLikes = solvers.sort((a, b) => a.likes.length - b.likes.length);
I am testing it by then console logging the solversByLikes array. This is the result:
0 LikesComponent.js:46
0 LikesComponent.js:46
0 LikesComponent.js:46
0 LikesComponent.js:46
2 LikesComponent.js:46
2 LikesComponent.js:46
But if I switch the a, and b, so that the sorting should be reversed, nothing changes.
var solversByLikes = solvers.sort((a, b) => b.likes.length - a.likes.length);
I tried replicating the issue like this:
allUsers = [{likes: [1, 2, 3, 4, 5, 6, 7, 8]}, {likes: [1, 2,]}, {likes: [1, 2, 3, 4, 5, 6,]}, {likes: [1, 2, 3, 4, 5,]}, {likes: [1, 2, 3, 4,]}, {likes: [1, 2, 3]}]
solversByLikes = allUsers.sort((a, b) => b.likes.length - a.likes.length);
solversByLikes.forEach(user => console.log(user.likes.length));
But this works as intended...
Any idea how to make it sort?
I'm not getting any error or anything.

Why is JavaScript object value are change when I push another value in array? [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 5 years ago.
Here is my code:
var arr = [];
var obj = {};
(function() {
for(let i = 1; i <= 10; i++) {
arr.push(i);
obj[i] = arr;
}
})();
This code gave me this output:
{
'1': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'2': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'3': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'4': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'5': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'6': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'7': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'8': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'9': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
'10': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
}
Why doesn't it give an output like this?
{
'1': [ 1 ],
'2': [ 1, 2 ],
'3': [ 1, 2, 3 ],
'4': [ 1, 2, 3, 4 ],
'5': [ 1, 2, 3, 4, 5 ],
'6': [ 1, 2, 3, 4, 5, 6 ],
'7': [ 1, 2, 3, 4, 5, 6, 7 ],
'8': [ 1, 2, 3, 4, 5, 6, 7, 8 ],
'9': [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
'10': [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
}
When you push, you're pushing the reference to the same array each time. What you actually want is to create a new array each time rather than reference the same one.
Check out this SO answer for more info Javascript by reference vs. by value
You could do this by pushing a copy arr using arr.slice or Array#from. At the very end arr will have all 10 numbers in it, but obj will look exactly like your output.
var arr = [];
var obj = {};
(function() {
for(let i = 1; i <= 10; i++) {
arr.push(i);
obj[i] = arr.slice();
}
console.log(obj);
})();

Categories

Resources