JSON formatting drill down issue - javascript

I am using dojo's arrayUtil.forEach to loop through my JSON object but when I get to data.graphs.metrics it does not continue because metrics is not an array. What options do I have?
xhr("/esp/files/eclwatch/ganglia.json", {
handleAs: "json"
}).then(function(data){
arrayUtil.forEach(data.graphs, function (item, idx) {
//never gets here.
});
});
}
//json file
{
"graphs": [
{
"name": "Bar",
"metrics":{
"metric": ["metric1, metric3"],
"metric": ["metric1", "metric4", "metric5"]
},
"time": ["Hour", "Month", "Week"]
}
]
}

Making it an array instead of giving it duplicate keys would make the most sense.
"metrics": [
["metric1, metric3"],
["metric1", "metric4", "metric5"]
],

Related

Javascript parse array of object strings into object of objects?

I am working with a 3rd party app that requires a specific structure of data for filtering a result set. I am struggling with figuring out how to parse this out as the end result isn't a conventional array of objects.
There is a function that takes in a list of IDs from an array and turns them into object strings:
Function:
// Input for articles is an array of IDs
// articles = ['kA10W000001UK2KSAW', 'kA1d0000000DB1CCAW', 'kA1d0000000DAsOCAW']
function createExclusion(articles){
let results = [];
articles.forEach(element => {
results.push(`"EqualsTo": {"Key": "sf_KnowledgeArticleId","Value": {"StringValue":"${element}"}}`)
})
return result;
}
Input Data:
let data = [
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA10W000001UK2KSAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DB1CCAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DAsOCAW"}}'
]
Desired End Result:
{
IndexId: 1,
PageSize: 2,
PageNumber: 3,
RequestedDocumentAttributes: ["_source_uri", "sf_ArticleNumber", "sf_KnowledgeArticleId"],
AttributeFilter: {
"NotFilter": {
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA10W000001UK2KSAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DB1CCAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DAsOCAW"
}
},
},
SortingConfiguration: {
"DocumentAttributeKey": "_document_title",
"SortOrder": "ASC"
}
};
}
I am trying to re-create the AttributeFilter data in the end result by taking the array of strings and parsing it into the correct form.
Example:
I was trying to get it to work with JSON.parse(), but the data isn't in the correct format for that.
Between either adjusting the createExclusion function or easily parsing it in its existing form, how can I go about turning the list of object strings into just objects as seen in the desired end result?
function parse(data) {
return {
IndexId: 1,
PageSize: 2,
PageNumber: 3,
RequestedDocumentAttributes: ["_source_uri", "sf_ArticleNumber", "sf_KnowledgeArticleId"],
AttributeFilter: {
"NotFilter": ? // Parse data here
},
SortingConfiguration: {
"DocumentAttributeKey": "_document_title",
"SortOrder": "ASC"
}
};
}
First, you cannot have an object with duplicated keys in JSON:
{
"NotFilter": {
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA10W000001UK2KSAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DB1CCAW"
}
},
"EqualsTo": {
"Key": "sf_KnowledgeArticleId",
"Value": {
"StringValue": "kA1d0000000DAsOCAW"
}
}
}
}
Your NotFilter value should be an array of objects.
Parsing JSON
Your JSON should be valid, prior to calling JSON.parse. Make sure you remove any trailing commas and wrap each line in curly-braces.
let data = [
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA10W000001UK2KSAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DB1CCAW"}},',
'"EqualsTo":{"Key":"sf_KnowledgeArticleId","Value":{"StringValue":"kA1d0000000DAsOCAW"}}'
]
const parsed = data.map(item => JSON.parse(`{${item.replace(/,$/, '')}}`));
console.log(parsed);
.as-console-wrapper { top: 0; max-height: 100% !important; }

How does one filter json after type?

So, I have a json which looks a little bit like this:
{
"data": {
"user": {
"edge_followed_by": {
"count": 22,
"page_info": {
"has_next_page": true,
"end_cursor": "Base64"
},
"edges": [
{
"node": {
"id": "id",
"username": "Username",
"full_name": "played",
"profile_pic_url": "URL"
}
}
]
}
}
}
}
And I want to filter out the username. How do I do that?
You could retrieve it with a map function there
const dataSample = {
"data": {
"user": {
"edge_followed_by": {
"count": 22,
"page_info": {
"has_next_page": true,
"end_cursor": "Base64"
},
"edges": [
{
"node": {
"id": "id",
"username": "Username",
"full_name": "played",
"profile_pic_url": "URL"
}
}
]
}
}
}
}
const getUsernames = data => {
return data.data.user.edge_followed_by.edges.map(e => e.node.username)
}
console.log(getUsernames(dataSample))
:)
This can be a little tricky to understand from the question first of all.
My interpretation of this is you want to extract a username
"Filtering" also could mean you want to remove something from a collection that passes a condition (or test) of some kind.
For example: Removing all even numbers from an array
let x = [1, 2, 4, 5, 6];
let filtered = x.filter(value => value % 2 === 0);
Now, I've looked at your json, and I think the best point of targeting this is by getting the "edges" property and running it through an inbuilt function like map; that could be used to get usernames. The edges is an array as well.
data.user.edge_followed_by.edges.map(userObject => userObject.username)
That would effectively remove all usernames from the edges if your tech stack of choice was javascript.
I got this info from a post like: https://coderin90.com/blog/2019/map-js

About C3.js chart data split

Since i am not familiar with C3.js library, i am bit confuse when i tried to split the Array data.
For instant i have some array value from a json.
var jsondata=[[123],[45],[56],[22]];
var jsondataName=[["apple"],["orange"],["banana"],["pear"]];
I tried to pass the first array jsondata into the chart but these values go into the same column which is not something i would like to see.
I want these array value become independent data and push the name into it
Please see the demo i made :
http://jsfiddle.net/q8h39/92/
And the result i want should looks like
Update the json data format :
"Name": apple,
"data": {
"value": 1434,
}
"Name": banana,
"data": {
"value": 342,
}
}
}
You can set the JSON object to data.json and then set data.keys.value to an array of values in that JSON:
var jsondata = [{
"Name": "apple",
"data": {
"value": 1434,
},
}, {
"Name": "banana",
"data": {
"value": 342,
}
}];
var chart = c3.generate({
data: {
json: jsondata,
keys: {
value: [
"name", "data.value"
]
},
type: "scatter"
//hide: true
}
});
http://jsfiddle.net/aendrew/mz9ccbrc/
n.b., You need C3 v0.4.11 for this (the dot syntax for keys.value was just added), and your JSON object needs to be an array (currently it's not valid).
If you want to convert the two arrays from your initial question to that format of JSON, try this:
d3.zip(jsondataName, jsondata)
.map((d) => Object({name: d[0][0], data: { value: d[1][0] } }));

Angular bind to filtered count

I have this array:
[
{
type: "hhh",
items: [
{
"name": "EGFR",
"type": "a",
"selected": true
}
]
},
{
type: "aaa",
items: [
{
"name": "mm",
"type": "b",
"selected": false
}
]
},
{
type: "ii",
items: [
{
"name": "pp",
"type": "bb",
"selected": true
}
]
}
]
I want to show a counter of the items with selected property "true".
I want it to be changed real time when change.
(Without watch and function)
Thnaks!
Here is the way:
var current_selected = {
get amount(){
var res = 0;
arr.forEach(function(item, i, arr) {
if (item.items[0].selected) res++;
})
return res;
}
}
Calling:
current_selected.amount
Fiddle
You can use JsonPath to get the count. Also using JsonPath has an added advantage of working on complex json structure. For the example you gave, you just need to include jsonpath js file and use the following in your script:
console.log(arr);
var filtered = jsonPath(arr, "$.[*].items[?(#.selected==true)]");
console.log(filtered);
console.log(filtered.length);
where arr is your json structure.
JsonPath can be got from :
https://code.google.com/archive/p/jsonpath/downloads
JsonPath help:
http://goessner.net/articles/JsonPath/
There might be updated version in other sources but that was the one I had worked on

how to loop through array of objects and separate nested array of arrays

I have JSON that I currently use for a kendo-ui chart. I need to use the data for a grid so I need to separate the nested data array of arrays into there own object. Javascript or linq.js will work fine. here is the JSON I am starting with.
customSeries = [{
"name": "Chantal Hamlet - Green Castle Homes",
"subId": "10223",
"bldId": "13551",
"data": [
[179900, 1386],
[214900, 1440],
[194500, 1496],
[217900, 1504],
[189900, 1542],
[184900, 1546],
[192500, 1570]
],
}, {
"name": "Ella Sea Condos - Sahnow Construction",
"subId": "9761",
"bldId": "27380",
"data": [
[199900, 1500]
]
}, {
"style": "smooth",
"color": "blue",
"data": [
[20000, 200],
[40000, 400],
[40000, 400]
],
"name": "Subject Property"
}]
I need to end up with 2 separate arrays.
First Array
Array1 = [{
"name": "Chantal Hamlet - Green Castle Homes",
"subId": "10223",
"bldId": "13551"
}, {
"name": "Ella Sea Condos - Sahnow Construction",
"subId": "9761",
"bldId": "27380"
}, {
"style": "smooth",
"color": "blue",
"name": "Subject Property"
}]
Second Array
Array2 = [
{
"data": [
[179900, 1386],
[214900, 1440],
[194500, 1496],
[217900, 1504],
[189900, 1542],
[184900, 1546],
[192500, 1570]
]
}, {
"data": [
[199900, 1500]
]
}, {
"data": [
[20000, 200],
[40000, 400],
[40000, 400]
]
}
]
You could use Array.prototype.map method.
var Array1 = customSeries.map(function(el) {
return {
name: el.name,
subId: el.subId,
bldId: el.bldId
};
});
var Array2 = customSeries.map(function(el) {
return {
data: el.data
};
});
Update:
The above code not work when your elements in customSeries don't have fixed keys except data.
If you using lodash, you could do this:
var Array1 = customSeries.map(function(el) {
return _.omit(el, 'data');
});
var Array2 = customSeries.map(function(el) {
return _.pick(el, 'data');
});
Depending on the length of the array, you might want to do this in a single pass. Using linq.js here won't help much for this, it'll just be added overhead with no real benefit.
If you don't mind obliterating your original data, you can process them both simultaneously by going through each of the items and add a copy of the data array to the second array while deleting the data from the item.
var array1 = data,
array2 = [];
array1.forEach(function (item) {
array2.push({
data: item.data
});
delete item.data;
});
If you'd rather keep your original data, you'll have to clone each item as you process them.
var array1 = [],
array2 = [];
data.forEach(function (item) {
var noData = yourCloneMethod(item); // replace call with preferred clone method
delete noData.data;
array1.push(noData);
array2.push({
data: item.data
});
});
You might want to look into using lodash, it has a lot of great functions for manipulating arrays and performing MapReduce functions.

Categories