Parsing json data to highcharts - json

I have searched and searched but i'm unable to find the solution yet.
I'm trying to load data into Highcharts with json from my server.
This is the json returned from my server:
[{
"x": "\/Date(1352674800000)\/",
"y": 621
}, {
"x": "\/Date(1352761200000)\/",
"y": 646
}, {
"x": "\/Date(1352847600000)\/",
"y": 690
}, {
"x": "\/Date(1352934000000)\/",
"y": 688
}, {
"x": "\/Date(1353020400000)\/",
"y": 499
}]
this is my highchart: (from my jsfiddle)
var seriesData = [];
for (var i = 0; i < data.length; i++) {
var dateString = data[i].x;
var x = dateString.replace(/\/Date\((\d+)\)\//, '$1');
var y = data[i].y;
seriesData.push([x, y]);
}
alert(seriesData);
var options = {
chart: {
renderTo: 'container'
},
xAxis: {
type: 'datetime',
labels: {
formatter: function() {
var monthStr = Highcharts.dateFormat('%a', this.value);
var firstLetter = monthStr.substring(0, 1);
return firstLetter;
}
}
},
series: []
};
function myfunk() {
options.series.push(seriesData);
chart = new Highcharts.Chart(options);
}
myfunk();
but my data is not showing.
i made a jsfiddel: http://jsfiddle.net/grVFk/12105/
Edit:
Now it's working but is the data point showing the wrong dates? http://jsfiddle.net/dxCHB/18/
If someone could help me i would be very grateful ! :)

You were very close. The series array needs to contain an object with a data member:
series: [
{
data:[]
}
]
You can then set it using:
function myfunk() {
options.series[0].data = seriesData;
I modified your jsfiddle: http://jsfiddle.net/dxCHB/
Format your date numerically
seriesData.push([x/1, y]);

Your data should be number, so you can use parseFloat() function to transform string to number.

Related

JSON array item validation

I'd like to have tooling to perform certain validations on JSON. Explanation with examples:
Given JSON fragment:
{
"optionsMinValue": 0
"optionsMaxValue": 56
"options": [
{
"name": "name1",
"value": 0
},
{
"name": "name2",
"value": 1
},
{
"name": "name3",
"value": 56
}
]
}
Validation examples:
Given the fragment above, the validation of optionsMaxValue should
pass.
Given the fragment above, if optionsMaxValue is changed to 55, then
the validation should fail.
Added bonus validation:
Check whether an item is included in the options array for every integer between optionsMinValue and optionsMaxValue. In other words, in the given fragment the array should contain 57 items with an item for each value from 0 to 56.
Existing tooling:
Does tooling exist that can be used relatively easily to perform these sorts of checks?
First thought is that something like json-schema validation could be done. It has been a few years since I looked at that as an option, so my hope is that tooling has emerged that is a homerun on this.
Ajv JSON schema validator - github link
const schema = {
type: "object",
properties: {
name: {type: "string"},
value: {type: "number", minimum: 0, maximum: 55},
},
required: ["name", "value"],
additionalProperties: false,
}
const option = {
"name": "name1",
"value": 0
},
const validate = ajv.compile(schema)
const valid = validate(data)
if (!valid) console.log(validate.errors)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/4.4.0/ajv.min.js"></script>
Joi package is best for these kind of validations
following Joi schema can be used to solve your requirement
Joi.object({
optionsMinValue: Joi.number().min(0).max(30).required(),
optionsMaxValue: Joi.number().min(56).max(100).required(),
options: Joi.array().items(
Joi.object({
name: Joi.string().required(),
value: Joi.number().min(0).max(56).required(),
})
),
});
Following is a sample code that works for your scenario
const inputData = {
optionsMinValue: 0,
optionsMaxValue: 56,
options: [
{
name: "name1",
value: 0,
},
{
name: "name2",
value: 1,
},
{
name: "name3",
value: 56,
},
],
};
const Joi = joi; // for node.js use - const Joi = require("joi");
// Schema for validation
const schema = Joi.object({
optionsMinValue: Joi.number().min(0).max(30).required(),
optionsMaxValue: Joi.number().min(56).max(100).required(),
options: Joi.array().items(
Joi.object({
name: Joi.string().required(),
value: Joi.number().min(0).max(56).required(),
})
),
});
const runValidation = (schema, inputData) => {
const validationResult = Joi.compile(schema)
.prefs({ errors: { label: "key" }, abortEarly: false })
.validate(inputData);
if (validationResult.error) {
// Validation failed
console.log("Error, validation failed");
// Set error message to string
const errorMessage = validationResult.error.details
.map((details) => details.message)
.join(", ");
console.log("failure reason - ", errorMessage);
return;
}
console.log("validation passed");
};
runValidation(schema, inputData);
<script src="https://cdn.jsdelivr.net/npm/joi#17.6.0/dist/joi-browser.min.js"></script>
Even if you use an existing tool, you should write validation rules for that tool. Since you are not an expert in any of these tools, it may be easier to write a few lines of code in your preferred language. For example, in JavaScript it might look like this:
function validateJson(jsonToValidate, maxValue = 56) {
if (jsonToValidate.optionsMaxValue !== maxValue) {
console.log("Failure on optionsMaxValue.");
return false;
}
if (jsonToValidate.options.length !== maxValue+1) {
console.log("Incorrect number of items.");
return false;
}
let values = jsonToValidate.options.map(a => a.value).sort();
if (values[0] !== 0 || values[maxValue] !== maxValue) {
console.log("Values out of desired sequence.");
return false;
}
let sum = values.reduce((a, b) => a + b, 0);
if (sum !== maxValue * (maxValue + 1) / 2) {
console.log("Values out of desired sequence.");
return false;
}
console.log("Validation PASSED.");
return true;
}
Let's try with truncated json object:
let jsonSample = {
"optionsMinValue": 0,
"optionsMaxValue": 2,
"options": [{
"name": "name1",
"value": 0
},
{
"name": "name2",
"value": 1
},
{
"name": "name3",
"value": 2
}
]
};
function validateJson(jsonToValidate, maxValue = 56) {
if (jsonToValidate.optionsMaxValue !== maxValue) {
console.log("Failure on optionsMaxValue.");
return false;
}
if (jsonToValidate.options.length !== maxValue+1) {
console.log("Incorrect number of items.");
return false;
}
let values = jsonToValidate.options.map(a => a.value).sort();
if (values[0] !== 0 || values[maxValue] !== maxValue) {
console.log("Values out of desired sequence.");
return false;
}
let sum = values.reduce((a, b) => a + b, 0);
if (sum !== maxValue * (maxValue + 1) / 2) {
console.log("Values out of desired sequence.");
return false;
}
console.log("Validation PASSED.");
return true;
}
validateJson(jsonSample, 2);

How to display json data with Angular-highcharts?

I am working an angular + node dashboard application and having trouble displaying JSON data in highcharts
JSON response:
[{"output":"FAIL","count":"4"},{"output":"PASS","count":"17"}]
public uat_deployment_chart_options: Highcharts.Options;
//this is the method I created to fetch the data
public get_uat_deployment_data() {
this.uat_deployment_subscription = this.curl_connection
.get_uat_deployment_data()
.subscribe(data => {
this.uat_deployment_data = data;
this.uat_deployment_data.forEach(val => {
val.count = parseInt(val.count)
});
this.uat_deployment_chart_options = {
title: {
text: "UAT Deployments"
},
series: [
{
data: this.uat_deployment_data,
type: "pie",
colors: ["#F44336", "#CDDC39"]
}
],
credits: {
enabled: false
},
};
});
}
If I manually paste the data and change the object keys to, "name" and "y" respectively the data is displayed, otherwise I get nothing
[{ "name": "FAIL", "y": 3 }, { "name": "PASS", "y": 16 }]

Can't get a sprite animation running in Pixijs on React

I am trying to follow along with the Pixijs guide provided here:
https://pixijs.github.io/examples/#/demos/animatedsprite-demo.js
- and after a bit of digging here is the sheet they use for their texture mapper
https://github.com/pixijs/examples/blob/gh-pages/required/assets/mc.json
To get an example up of a simple animated sprite. The issue that I am having is that I am following along almost exactly and I am getting an error - I do not know what is causing the problem and I don't know how to proceed debugging on my own.
The example has:
var app = new PIXI.Application();
document.body.appendChild(app.view);
app.stop();
PIXI.loader
.add('spritesheet', 'required/assets/mc.json')
.load(onAssetsLoaded);
function onAssetsLoaded() {
// create an array to store the textures
var explosionTextures = [],
i;
for (i = 0; i < 26; i++) {
var texture = PIXI.Texture.fromFrame('Explosion_Sequence_A ' + (i+1) + '.png');
explosionTextures.push(texture);
}
Where I have:
componentDidMount(){
this.renderer = PIXI.autoDetectRenderer(1366, 768);
this.refs.gameCanvas.appendChild(this.renderer.view);
this.stage = new PIXI.Container();
this.stage.width = 400;
this.stage.height = 400;
console.log(littlemarioforwardwalkjson)
PIXI.loader
.add(littlemarioforwardwalkpng, littlemarioforwardwalkjson)
.load(()=>this.spriteLoaded());
// console.log(PIXI.utils.TextureCache);
}
spriteLoaded(){
console.log('yolo');
var frames = [];
var index = 0;
console.log('hello there sailor');
console.log(PIXI.utils.TextureCache)
for (var i = 0; i < 3; i++) {
index = i+46;
var texture = PIXI.Texture.fromFrame("mario_characters1_"+index+".png");
marioTextures.push(texture);
}
}
The error I am getting is:
Error: the frameId “mario_characters1_46.png” does not exist in the texture cache
This is frustrating as my texturepacker json file is displaying correctly:
{"frames": {
"mario_characters1_46.png":
{
"frame": {"x":0,"y":0,"w":12,"h":15},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":12,"h":15},
"sourceSize": {"w":12,"h":15},
"pivot": {"x":0.5,"y":0.5}
},
"mario_characters1_47.png":
{
"frame": {"x":12,"y":0,"w":11,"h":16},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":11,"h":16},
"sourceSize": {"w":11,"h":16},
"pivot": {"x":0.5,"y":0.5}
},
"mario_characters1_48.png":
{
"frame": {"x":23,"y":0,"w":15,"h":16},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":15,"h":16},
"sourceSize": {"w":15,"h":16},
"pivot": {"x":0.5,"y":0.5}
}},
"meta": {
"app": "http://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "littlemarioforwardwalk.png",
"format": "RGBA8888",
"size": {"w":38,"h":16},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:ae9c1a55b9f5884f4a4c0182ea720ca9:80c341baf7877296bb8143f4c51a5998:383ea93646790c53db2201f0624e779e$"
}
}
If I console.log(PIXI.utils.TextureCache) I get:
{data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAQCAYAAAB6Hg0eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABUUlEQVRIx6VVPZqFIAxM/DwE1+B1WL5j0NrucWxtPcYr106uwS2yxQobMWB0aVSciTP5QYRikTVU7mGI+BT3lIdXJCmIFqcRVeP1fHN9xXzvrP/dCws46wG/FryLK9cdXpduvkegBE7Xg9vJE02etLhy/y6vE52F5eCMP2txkrg7POSOJDc1UVe4YT72rzZ+4qGU0mpjsj7Q4p7GF13lrGwG1leEYQakyVMiZvf7+1qWWnH5MEi8QwY0ZSsxrY+k7NQ4tUnNzZ8CcIKmRBk/vsFtBtxmxFI5689ZGd85RjbHDJxKc3Xw1coiYfOE7YZaByyPP8yAfesDYllZXznrAez+Yv60h+Xi1CdriJe1KzMg/U74M4aIJxNM1NNfUbn6v4aNhylaoTExISKBIdg+pwaGcJ7IFeKhIlx8TbRqvCVxUqYlPMfVjhO1MM3SiP+PuB9QuQ5f9MhyUAAAAABJRU5ErkJggg==: Texture}
So it would seem that the error is saying that the Texture Cache is only seeing one image blob - however, calling Texture.fromFrame is how the example on the website says to get it to work, and I think I am reproducing the code very closely.
If anyone has any ideas please let me know.
It was not easy to find an example with React, if that can help someone.
import React from "react";
import KingHuman from "./img/kinghuman/Idle/Idle.png";
import KingHumanJson from "./img/kinghuman/Idle/Idle.json";
import * as PIXI from 'pixi.js';
import { Stage, Container, AnimatedSprite } from '#inlet/react-pixi';
const PixiGame = () => {
const willMount = useRef(true);
const [textures, setTextures] = useState([]);
const loadSpritesheet = () => {
const baseTexture = PIXI.BaseTexture.from(KingHuman);
const spritesheet = new PIXI.Spritesheet(baseTexture, KingHumanJson);
spritesheet.parse(() => {
setTextures( Object.keys(spritesheet.textures).map((t) => spritesheet.textures[t]));
});
}
// Hooks way to do ComponentWillMount
if (willMount.current) {
loadSpritesheet();
willMount.current = false;
}
return (
<Stage width={300} height={300} options={{ backgroundColor: 0xeef1f5 }}>
<Container position={[150, 150]}>
<AnimatedSprite
anchor={0.5}
textures={textures}
isPlaying={true}
initialFrame={0}
animationSpeed={0.1}
/>
</Container>
</Stage>
);
}
export default PixiGame;
Yes I also struggled to get information for react on this. Had a sprite sheet without a json and created a function to generate the frame data. Adding on to the other answer is my code snippet
import React, { useRef, useState } from "react";
import KingHuman from "../../assets/mc.png";
import * as PIXI from 'pixi.js';
import { Stage, Container, AnimatedSprite } from '#inlet/react-pixi';
const generateFrames = (animationWidth, animationHeight, rowSize, colSize, fileWidth, fileHeight, imageName) => {
let generated = {
"frames": {},
"meta": {
"app": "Splash Software Assessment",
"version": "1.0",
"image": imageName,
"format": "RGBA8888",
"size": { "w": fileWidth, "h": fileHeight },
"scale": "1",
"smartupdate": ""
}
};
for (let i = 0; i < rowSize; i++) {
for (let j = 0; j < colSize; j++) {
const px = animationWidth * i;
const py = animationHeight * j;
const image = `${imageName}${px}${py}.png`
generated.frames[image] = {
"frame": { "x": px, "y": py, "w": animationWidth, "h": animationHeight },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": px, "y": py, "w": animationWidth, "h": animationHeight },
"sourceSize": { "w": animationWidth, "h": animationHeight }
}
}
}
return generated;
};
const PixiGame = () => {
const willMount = useRef(true);
const [textures, setTextures] = useState([]);
const KingHumanJson = generateFrames(240, 240, 4, 8, 1024, 2048, "mc.png")
const loadSpritesheet = async () => {
const baseTexture = PIXI.BaseTexture.from(KingHuman);
const spritesheet = new PIXI.Spritesheet(baseTexture, KingHumanJson);
const textures = await spritesheet.parse();
setTextures(Object.keys(textures).map((t) => textures[t]));
}
// Hooks way to do ComponentWillMount
if (willMount.current) {
loadSpritesheet();
willMount.current = false;
}
return (
<Stage width={300} height={300} options={{ backgroundColor: 0xeef1f5 }}>
<Container position={[150, 150]}>
<AnimatedSprite
anchor={0.5}
textures={textures}
isPlaying={true}
initialFrame={0}
animationSpeed={0.1}
/>
</Container>
</Stage>
);
}
export default PixiGame;

HighChart with multple JSON api data

I am creating a linechart which contain data from different JSON files, and the codes below is working but i'd like to know how may i group up these JSON data from different apis into one by a for each loop to shorter the codes.
//consider the vol1- vol10 looks like var vol1 = ['1123', '1234','5436'];
//because i have other method the convert it to an arrray
//Xvol1 is just something like Xvol1=["Jan","Feb","Mar"]
$('#trendChart').highcharts({
chart: {
type: 'spline'
},
title: {
text: false
},
xAxis: {
categories : Xvol1
},
yAxis: {
title: {
text: 'Volume',
},
min: 0
},
plotOptions: {
spline: {
marker: {
enabled: true
}
}
},
series: [{
name: $(".profileName0").html(),
data: vol1
},
{
name: $(".profileName1").html(),
data: vol2
},
{
name: $(".profileName3").html(),
data: vol3
},
{
name: $(".profileName2").html(),
data: vol4
},
{
name: $(".profileName4").html(),
data: vol5
},
{
name: $(".profileName5").html(),
data: vol6
},
{
name: $(".profileName6").html(),
data: vol7
},
{
name: $(".profileName7").html(),
data: vol8
},
{
name: $(".profileName8").html(),
data: vol9
},
{
name: $(".profileName9").html(),
data: vol10
},
]
});
UPDATE 1:
I have tried but it doesn't seem like working.
var series = [];
for(i = 0; i < 10; i++){
series.push({name: $('.profileName'+i+'"').html(),, data: vol[i]});
}
$('#trendChart').highcharts({
chart: {
type: 'spline'
},
title: {
text: false
},
xAxis: {
categories : Xvol1
},
yAxis: {
title: {
text: 'Volume',
},
min: 0
},
plotOptions: {
spline: {
marker: {
enabled: true
}
}
},
series: [series]
});
});
After i generate the data by a for loop successfully, i am now struggle about how to update the data, i tried to update it using setData() but seem it needs so adjustment in order to work.
var seriesData = [vol1, vol2, vol3, vol4, vol5, vol6 , vol7, vol8, vol9, vol10]; // add all the vols. I have used 2 for example
var series = [];
for(i = 0; i < 5; i++){
series.push({name: names[i], data: seriesData[i]});
}
var trendChart12w = $('#trendChart').highcharts();
trendChart12w.series[0].setData(series);
Solution :
var dataCounting = $(".DataCount").last().html();
var seriesData = [vol1, vol2, vol3, vol4, vol5, vol6 , vol7, vol8, vol9, vol10]; // add all the vols. I have used 2 for example
var trendChart1y = $('#trendChart').highcharts();
trendChart1y.xAxis[0].setCategories(Xvol1);
for(i = 0; i < dataCounting; i++){
trendChart1y.series[i].setData(seriesData[i]);
}
You can an array of the names like var names = [all the names] and an array of your data like var seriesData = [vol1, vol2...]
And then do
var series = [];
for(i = 0; i < names.length; i++){
series.push({name: names[i], data: seriesData[i]});
}
And then set this as your chart series.
UPDATE
Do this outside of your chart.
var seriesData = [vol1, vol2]; // add all the vols. I have used 2 for example
var names = [$(".profileName0").html(), $(".profileName1").html()] // add all names
var series = [];
for(i = 0; i < names.length; i++){
series.push({name: names[i], data: seriesData[i]});
}
And then in your chart, where you set the series, just do
series: series

streaming multiple series to highcharts

I'm using websockets to stream valid JSON to highcharts.js. My goal is to chart a few lines simultaneously on the same graph. The JSON, which I control, contains data 4-16 series (called parsers) that I'd like overlay with highcharts. Example of JSON:
[
{
"y": 91,
"x": 1403640998,
"name": "parser1"
},
{
"y": 184,
"x": 1403640998,
"name": "parser2"
},
{
"y": 26,
"x": 1403640998,
"name": "parser3"
}
]
I can get a single line to graph, but they get combined into a single series. I'd like to dynamically adjust the series based on the number of parsers I'm monitoring. If my JSON contains information for 3 parsers, like I posted above, I'd like to see 3 lines automatically update every second.
As you can see, I can only get 1 to show.
My HTML
<script type="text/javascript">
$(function () {
$('#container').highcharts({
chart: {
type: 'spline',
events: {
load: function () {
var $message = $('#message');
var connection = new WebSocket('ws://x.x.x.x:8888/ws');
var self = this;
connection.onmessage = function(event) {
var data = JSON.parse(event.data);
var series = self.series[0];
var redrawVal = true;
var shiftVal = false;
if (series.data && series.data.length > 25) {shiftVal = true;}
var newseries = {
name: '',
x: 0,
y: 0
};
$.each(data, function(i,item){
newseries.name = item.name;
newseries.x = item.x;
newseries.y = item.y;
console.log(newseries)
series.addPoint(newseries, redrawVal, shiftVal);
});
};
}
}
},
title: {
text: 'Using WebSockets for realtime updates'
},
xAxis: {
type: 'date'
},
series: [{
name: 'series',
data: []
}]
});
});
Can someone help me get multiple series to dynamically display in highcharts.js?
The general idea should be that for each series you set it's id. Then you cna get that series this way: chart.get(id). So if you have series, then add point to that series, if not, then create new one, just like this: http://jsfiddle.net/9FkJc/8/
var self = this;
data = [{
"y": 91,
"x": 1403640998,
"name": "parser1"
}, {
"y": 184,
"x": 1403640998,
"name": "parser2"
}, {
"y": 26,
"x": 1403640998,
"name": "parser3"
}];
var series = self.series[0];
var redrawVal = true;
$.each(data, function (i, item) {
var series = self.get(item.name);
if (series) { // series already exists
series.addPoint(item, redrawVal, series.data.length > 25);
} else { // new series
self.addSeries({
data: [item],
id: item.name
});
}
});