Issues with JSON formatting for data object in Grafana - javascript

Data is not coming in with proper JSON formatting, so I'm having to loop through items in the array to fix the formatting, parsing the changed items and I cannot use the new object(s) when everything is finished because it is no longer in an array. The data is coming in as follows:
data [datapoints: [0..1..]
target: "up{cluster="bluehills_c3260_cluster",component="atr",datacenter="bluehills",hostname="ny-153-177"...}"]
Is there an easier way to convert this using a .map function or some other method to make things cleaner and get the desired result?
I've tried several methods including .replace, .map, and .push. I've also tried JSON.stringify, but nothing else seems to work except what I currently have.
onDataReceived(data) {
var i;
for (i = 0; i < data.length; i++) { // Loop through data array
var txt = data[i].target; // Create the variable to store the data target
var j;
for (j = 0; j <= txt.length; j++) { // Loop through the data target
var newObj = txt.slice(2,j); // Remove "up"
var filteredObj = newObj // Change over to JSON format...
.replace(/=/g,' : ')
.replace(/,/g,', ')
.replace(/{/g,'{ ')
.replace(/cluster/g,'"cluster"')
.replace(/component/g,'"component"')
.replace(/datacenter/g,'"datacenter"')
}
var dataObj = filteredObj.replace(/_"cluster"/gi,'_cluster');
var finalObj = JSON.parse(dataObj);
console.log("finalObj", dataObj);
}
}
What I want is a single array with the proper JSON format for the data (target) coming in.

How about this?
const myReg = /([\w\s]+)=\"([^"]*)\"/g
const str = `data [datapoints: [0..1..] target: "up{cluster="bluehills_c3260_cluster",component="atr",datacenter="bluehills",hostname="ny-153-177"...}"]`;
let matches = null;
const resultsJson = {};
while(matches = myReg.exec(str)){
resultsJson[matches[1]] = matches[2];
}
{ cluster: 'bluehills_c3260_cluster',
component: 'atr',
datacenter: 'bluehills',
hostname: 'ny-153-177' }
Not sure if this is how you want to have the data stored but that part would be pretty easy to customize.

onDataReceived(data){
this.createCosmo(data);
}
createCosmo(data) {
var arr = $.map(data,function(value){
return value.target;
});
var arr2 = $.map(arr,function(value){
var newObj = value.slice(2); // Remove "up"
var filteredObj = newObj // Change over to JSON format
.replace(/=/g,' : ')
.replace(/,/g,', ')
.replace(/{/g,'{ ')
.replace(/cluster/g,'"cluster"')
.replace(/component/g,'"component"')
.replace(/datacenter/g,'"datacenter"')
.replace(/hostname/g,'"hostname"')
.replace(/instance/g,'"instance"')
.replace(/job/g,'"job"')
.replace(/resilience_group/g,'"resilience_group"')
.replace(/_"cluster"/gi,'_cluster')
.replace(/-"cluster"/gi,'-cluster');
var finalObj = JSON.parse(filteredObj); // Parse the Object into JSON
return finalObj;
});
}

Related

Searching a JSON formatted array

I am trying to search the below array which is in JSON format.
[{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"807"},
{"SystemID":"62750003","ApparentPower":"796"}]
I want to first check the first element in this case "SystemID" and append all the values of "SystemID" to op1 array I have created. I am not sure how to do this, my code to search the array is below (JS file):
$(document).ready(function() {
$.ajax({
url: "http://localhost/chartjs/data.php",
method: "GET",
success: function(data) {
op1 = [];
if (data[i] == 'SystemID') {
for(var i in data) {
op1.push(data[i]['SystemID'])
}
}
}
}
}
When I run this code now, op1 is empty.
I want op1 to have all the values of SystemID from the JSON array.
UPDATE: I want to check IF the element is "SystemID" and if so, appened the first element to "op1". The first element and second element in my JSON data could change, so I want to check that first and then append the first element to "op1". Also I want to check the second element, and append the second elements value to "op2" array.
As i understand you want all the SystemID in the array op1:
const data = [{"SystemID":"62750003","ApparentPower":"822"},{"SystemID":"62750003","ApparentPower":"822"}, {"SystemID":"62750003","ApparentPower":"807"},{"SystemID":"62750003","ApparentPower":"796"}];
const op1 = data.map(item => item.SystemID);
console.log(op1);
You need something like that , you are missing the for loop
var data = [{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"807"},
{"SystemID":"62750003","ApparentPower":"796"}]
var op1 = [];
var op2 = [];
for(let i=0; i < data.length;i++){
for(let item in data[i]){
if(item == "SystemID"){
op1.push(data[i][item])
}
if(item == "ApparentPower"){
op2.push(data[i][item])
}
}
}
console.log(op1)
console.log(op2)
if you wanna use ECMA6
let data = [{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"807"},
{"SystemID":"62750003","ApparentPower":"796"}]
let op1 = data.map(item => item.SystemID);
let op2 = data.map(item => item.ApparentPower);
console.log(op1)
console.log(op2)
if you wanna global concept
let data = [{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"807"},
{"SystemID":"62750003","ApparentPower":"796"}]
let data_keys = Object.keys(data[0])
let result = []
for(let item in data_keys){
result.push([])
}
for(let i=0; i < data.length;i++){
for(key in data_keys){
if(Object.keys(data[i])[key] == data_keys[key]){
result[key].push(Object.values(data[i])[key])
}
}
}
for(let k=0; k<result.length;k++){
console.log(result[k])
}
console.log(result)
You want to check if the first key in particular is SystemID ? if that's the case you could try
const data = [
{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"807"},
{"SystemID":"62750003","ApparentPower":"796"},
{"NOTASystemID":"6sss","ApparentPower":"796"}
];
const op = data
.filter(element => Object.keys(element)[0]==="SystemID") //filtering out element with first key sysID
.map(element => element.SystemID);
console.log(op);
As per my understanding your code will be like this
var json = [{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"822"},
{"SystemID":"62750003","ApparentPower":"807"},
{"SystemID":"62750003","ApparentPower":"796"}];
var myArray =[];
json.forEach(function (item) {
if(item.SystemID) {
myArray.push(item.SystemID);
}
});
console.log(myArray);
Try This,
var data = '[{"SystemID":"62750003","ApparentPower":"822"},{"SystemID":"62750003","ApparentPower":"822"},{"SystemID":"62750003","ApparentPower":"807"},{"SystemID":"62750003","ApparentPower":"796"}]';
var op1 = [];
$.each(JSON.parse(data),function(i,item){
op1[i] = item.SystemID;
});
console.log(op1);
Assuming you have already parsed the JSON data, you can just map through the array and use the hasOwnProperty() method to check if each object in the array has SystemID or not and if it does, push it's value to the op1 array.
Trying to retrieve elements in an object using index is not reliable since object properties are unsorted.
var data = [{"SystemID":"62750003","ApparentPower":"822"},{"SystemID":"62750003","ApparentPower":"822"},{"SystemID":"62750003","ApparentPower":"807"},{"SystemID":"62750003","ApparentPower":"796"}];
var op1 = data.map(e => {
if (e.hasOwnProperty("SystemID")) {
return e.SystemID;
} else {
// do something else since current mapped object doesn't have "SystemID"
}
});
console.log(op1);

Create nested Javascript Object dynamically

I have got a . (dot) separated string, from which I want to create nested JSON object. The length of the string is not fixed. For example,
var string = 'a.b.c.d';
Then my JSON object should be as following:
a: {
b: {
c:{
d: {
//Some properties here.
}
}
}
}
I've tried following code:
var packageName = "a.b.c.d"
var splitted = packageName.split('.');
var json = {};
for(var i=0;i<splitted.length-1;i++){
json[splitted[i]] = splitted[i+1];
}
But this returns
{
a: 'b',
b: 'c',
c: 'd'
}
But this is not what I want. I've also searched on google and found similar questions, but no solutions answer my problem. For example this.
A good use case for reduce
packageName = "a.b.c.d";
initProps = {hi: 'there'};
obj = packageName.split('.').reduceRight((o, x) => ({[x]: o}), initProps);
console.log(JSON.stringify(obj))
If you find loops easier to work with, a loop could be written concisely as
result = {};
ptr = result;
for (let prop of packageName.split('.'))
ptr = ptr[prop] = {};
You need to create a new object each time and attribute it to the last object created. And it goes until splitted.length, not splitted.length - 1, because you're using <, not <=.
var packageName = "a.b.c.d";
var splitted = packageName.split('.');
var json = {};
var current = json;
for (var i = 0; i < splitted.length; i++) {
current[splitted[i]] = {};
current = current[splitted[i]];
}
console.log(json);
You may use the last splittted part as property for some payload.
I suggest to keep the object reference and use a temporary variable for aceessing an creating a new property, if necessary.
Please avoid the use of JSON for not stringified objects.
var packageName = "a.b.c.d",
splitted = packageName.split('.'),
result = {},
temp = result,
i;
for (i = 0; i < splitted.length - 1; i++) {
temp[splitted[i]] = temp[splitted[i]] || {};
temp = temp[splitted[i]];
}
temp[splitted[i]] = { some: 'data' };
console.log(result);

How can I capture a hash to Object in functional JavaScript?

I'm writing a piece of code in JavaScript for modern browser. I'm not using lodash or underscore as we want to keep the library as small as possible.
For example,
If the url comes like this. http://something.com/#hash=value
And the app is configured to capture key hash then the result would be this. Nothing fancy. I was just wondering if there's a better way or simple way to do this.
{
'hash': 'value'
}
The code
var config = Object.assign({}, {
capturedHashParams: ['hash']
});
var hashValue = '#hash=value1'.substr(1);
var capturedHashParams = {};
if (config.capturedHashParams && Array.isArray(config.capturedHashParams)) {
var splitedHash = hashValue.split('=');
if (splitedHash.length > 0) {
var key = splitedHash[0] || '';
var value = splitedHash[1] || '';
if (key && value) {
config.capturedHashParams.forEach(function(hp) {
if (hp.toLowerCase().indexOf(key.toLowerCase()) > -1) {
capturedHashParams[key] = value;
}
});
}
}
}
console.log(capturedHashParams);
https://jsfiddle.net/c92p0rfm/2/
i think you are watching for something like this:
var output = [];
var hashString = window.location.hash;
var hashArray = hash.split('&');
for(var index = 0; index < hashArray.length; index++){
var text = hashArray[index];
var tempArray= text.split('=');
var object = {
id: tempArray[0],
value: tempArray[1]
};
output[index] = object;
}
now output looks like this:
[
{
id: "hash",
value: "value"
}
]
Your question is somewhat ambiguous. It appears that you want to extract key/value pairs from an url hash and return as a JavaScript object. I am bit uncertain about whether you want to extract all key/value pairs or only those provided in a config object. I am also a bit uncertain as to whether you want a solution within a strict functional programming paradigm, or just a plain solution with a small code footprint. I will assume the latter.
A straightforward approach to capture all key/value pairs:
var url = 'http://something.com/#hash=value&anotherHash=value';
//extract key=value pairs from url
var params = url.split('#').pop().split('&');
//assign to data object
for(var data = {}, i = 0, temp; i < params.length; i++){
// extract array [key, value]
temp = params[i].split('=');
// assign to data object
data[temp[0]] = temp[1];
}
console.log(data);
A more compact solution to do the same with .reduce():
var url = 'http://something.com/#hash=value&anotherHash=value';
var data = url
.split('#')
.pop()
.split('&')
.reduce(function(obj, keyval){
keyval = keyval.split('=');
obj[keyval[0]] = keyval[1];
return obj;
}, {});
console.log(data)
If you want to configure which keys to extract:
var url = 'http://something.com/#hash=value&anotherHash=value&notThisHash=value';
//config object
var keysToCapture = [
'hash',
'anotherHash'
];
var data = url
.split('#')
.pop()
.split('&')
.reduce(function(obj, keyval){
keyval = keyval.split('=');
if(keysToCapture.indexOf(keyval[0]) > -1){
obj[keyval[0]] = keyval[1];
}
return obj;
}, {});
console.log(data)
Which you could capture in a reusable function like this:
function extractParamsObject(url, keysToCapture){
return url
.split('#')
.pop() //hash/fragment: everything after the last #
.split('&')
.reduce(function(obj, keyval){
keyval = keyval.split('=');
if(keysToCapture.indexOf(keyval[0]) > -1){
obj[keyval[0]] = keyval[1];
}
return obj;
}, {});
}
console.log(extractParamsObject(
'http://something.com/#hash=value&anotherHash=value&notThisHash=value',
['hash', 'anotherHash']
));

Split nested array into multiple arrays

I have a string that looks like this:
str = {1|2|3|4|5}{a|b|c|d|e}
I want to split it into multiple arrays. One containing all the first elements in each {}, one containing the second element, etc. Like this:
arr_0 = [1,a]
arr_1 = [2,b]
arr_2 = [3,c]
.....
The best I can come up with is:
var str_array = str.split(/}{/);
for(var i = 0; i < str_array.length; i++){
var str_row = str_array[i];
var str_row_array = str_row.split('|');
arr_0.push(str_row_array[0]);
arr_1.push(str_row_array[1]);
arr_2.push(str_row_array[2]);
arr_3.push(str_row_array[3]);
arr_4.push(str_row_array[4]);
}
Is there a better way to accomplish this?
Try the following:
var zip = function(xs, ys) {
var out = []
for (var i = 0; i < xs.length; i++) {
out[i] = [xs[i], ys[i]]
}
return out
}
var res = str
.split(/\{|\}/) // ['', '1|2|3|4|5', '', 'a|b|c|d|e', '']
.filter(Boolean) // ['1|2|3|4|5', 'a|b|c|d|e']
.map(function(x){return x.split('|')}) // [['1','2','3','4','5'], ['a','b','c','d','e']]
.reduce(zip)
/*^
[['1','a'],
['2','b'],
['3','c'],
['4','d'],
['5','e']]
*/
Solution
var str = '{1|2|3|4|5}{a|b|c|d|e}'.match(/[^{}]+/g).map(function(a) {
return a.match(/[^|]+/g);
}),
i,
result = {};
for (i = 0; i < str[0].length; i += 1) {
result["arr_" + i] = [+str[0][i], str[1][i]];
}
How it works
The first part, takes the string, and splits it into the two halves. The map will return an array after splitting them after the |. So str is left equal to:
[
[1,2,3,4,5],
['a', 'b', 'c', 'd', 'e']
]
The for loop will iterate over the [1,2,3,4,5] array and make the array with the appropriate values. The array's are stored in a object. The object we are using is called result. If you don't wish for it to be kept in result, read Other
Other
Because you can't make variable names from another variable, feel free to change result to window or maybe even this (I don't know if that'll work) You can also make this an array
Alternate
var str = '{1|2|3|4|5}{a|b|c|d|e}'.match(/[^{}]+/g).map(function(a) { return a.match(/[^|]+/g); }),
result = [];
for (var i = 0; i < str[0].length; i += 1) {
result[i] = [+str[0][i], str[1][i]];
}
This is very similar except will generate an Array containing arrays like the other answers,

How do I define an associative array?

I want to define what I understand is an associative array (or maybe an object) such that I have entries like the following:
"Bath" = [1,2,5,5,13,21]
"London" = [4,7,13,25]
I've tried the following:
var xref = new Object;
xref = [];
obj3 = {
offices: []
};
xref.push(obj3);
Then cycling through my data with
xref[name].offices.push(number);
But I get "TypeError: xref[name] is undefined". What am I doing wrong ?
Use an object like you do with obj3:
var xref = {};
xref.obj3 = obj3;
var name = 'obj3';
xref[name].offices.push(number);
var obj = {
arr : [],
}
var name = "vinoth";
obj.arr.push(name);
console.log(obj.arr.length);
console.log(obj.arr[0]);
obj.prop = "Vijay";
console.log(obj.prop);
You can use an object literal.
I realised that all I really wanted was a 2 dimensional array with the first dimension being the key (ie. "BATH", "LONDON") and the second being the list of cross-references (ie. 1,2,5,5,13,21) - so I don't need to understand the Object route yet ! The other suggestions may well work and be "purer" but the 2 dimensional array is easier for my old-fashioned brain to work with.
So I did the following:
var xref = [];
// go through source arrays
for (i = 0; i < offices.length; i++) {
for (j = 0; j < offices[i].rel.length; j++) {
// Check if town already exists, if not create array, then push index
if (xref[offices[i].rel[j].town] === undefined) {
xref[offices[i].rel[j].town] = [];
alert('undefined so created '+offices[i].rel[j].town);
};
xref[offices[i].rel[j].town].push(i); // Add index to town list
};
};
I believe from reading other posts that I would have problems if any of the 'offices[i].rel[j].town' were set to undefined but the data doesn't have this possibility.
Now I can access a cross-reference list by doing something like:
townlist = "";
for (i = 0; i < xref["BATH"].length; i++) {
townlist += offices[xref["BATH"][i]].name+' ';
};
alert(townlist);

Categories