I am trying to extract multiple values from multiple JSON arrays to create a pie chart.
The below function only able to get a single value but what I want is to get all values from those arrays for example, tag should return "untagged","HK_Online","HK_Order/Change address" but it only return "HK_Online" at the moment.
My function node
var value = msg.payload.lines[0][1].value;
var tag = msg.payload.lines[1][0].value;
msg.topic = tag;
msg.payload = value;
return msg;
JSON data
{
"axes": {
"x": [
{ "name": "Tag","type": "string" },
{ "name": "Total","type": "number" },
{ "name": "Percentage","type": "percent" },
{ "name": "Delta", "type": "delta" }
]
},
"lines": [
[
{ "type": "string","value": "Untagged" },
{ "type": "number","value": 1 },
{ "type": "percent","value": 20 },
{ "type": "delta", "value": 100 }
],
[
{ "type": "string","value": "HK_Online" },
{ "type": "number","value": 4 },
{ "type": "percent","value": 80 },
{ "type": "delta","value": 100 }
],
[
{ "type": "string","value": "HK_Order/Change address" },
{ "type": "number","value": 1 },
{ "type": "percent","value": 20 },
{ "type": "delta","value": 100 }
]
]
}
You can use map method to create new array from the lines array
let lines = msg.payload.lines
let tag = lines.map(item => item[0].value)
let value = lines.map(item => item[1].value)
Related
I have a nested array like below. There are about 100 de objects in the array. The de objects also have deg[0] array but most likely I will only have the first index. Now the trick is that the de are subset of deg. Which means each deg can have say 10 de. How can I retrieve the deg and there associated de and map it into a new array like:
newArray = [
deg1: [
{de1},
{de2}
],
deg2: [
{de1},
{de2}
]
]
Here is my nested array. I posted four but the list is over a 100.
{
"name": "Report",
"id": "2YYUEZ6I1r9",
"dse1": [
{
"de1": {
"name": "Number",
"id": "HjMOngg3kuy",
"de1-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "TB",
"id": "2XJB1JO9qX8"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de1": {
"name": "Number of",
"id": "a3dtGETTawy",
"de1av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Tertiary",
"id": "w99RWzXHgtw"
}
]
}
}
]
}
Group array of objects by property (this time a property to be matched by a reg exp) using Array.reduce.
Update: Ignoring missing keys.
var input={name:"Report",id:"2YYUEZ6I1r9",dse1:[{de1:{name:"Number",id:"HjMOngg3kuy","de1-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"TB",id:"2XJB1JO9qX8"}]}},{de2:{name:"Number of",id:"a3dtGETTawy","de2-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de1:{name:"Number of",id:"a3dtGETTawy",de1av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de2:{name:"Number of",id:"a3dtGETTawy",de2av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Tertiary",id:"w99RWzXHgtw"}]}}]}
var reg = new RegExp("^de[0-9]+$");
var reg2 = new RegExp("^deg[0-9]+$");
let obj = input['dse1'].reduce(function(agg, item) {
// do your group by logic below this line
var key = Object.keys(item).find(function(key) {
return key.match(reg) ? key : null;
})
if (key) {
var key2 = Object.keys(item[key]).find(function(key) {
return key.match(reg2) ? key : null;
})
agg[key] = agg[key] || [];
if (key2) {
var to_push = {}
to_push[key2] = item[key][key2]
agg[key].push(to_push)
}
}
// do your group by logic above this line
return agg
}, {});
console.log(obj)
.as-console-wrapper {
max-height: 100% !important;
}
I have an array of widgets containing multiple objects. Each object contains an array called cards which contains just a single object. I need help with extracting all the cards object and making a new cards array containing all the cards as elements
{
"widgets" : [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
}
]
}
How I want is
{
"widgets": [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
},
{
"data": {},
"layout": 1
}
]
}
]
}
You can loop over the original object orig and extract it's cards into a new array allCards:
const allCards = [];
for (let widget of orig.widgets) {
allCards.push(widget.cards[0]);
}
Then you can construct a new object with these extracted cards.
Given your requirement, the below might work.
let x = {
"widgets" : [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
}
]
}
let y = {"widgets": [{...x.widgets[0], "cards":[]}]};
x.widgets.forEach(el => y.widgets[0].cards.push(...[].concat(el.cards)));
You can try this code that taek into account the type of each widget :
object = {
"widgets" : [
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Table",
"cards": [
{
"data": {},
"layout": 1
}
]
},
{
"type": "Grid",
"cards": [
{
"data": {},
"layout": 1
}
]
}
]
}
new_object = {"widgets" : []}
for (let i=0; i < object["widgets"].length; i++) {
exist = false
for (let j=0; j < new_object["widgets"].length; j++) {
if (new_object["widgets"][j]["type"] === object["widgets"][i]["type"]){
exist = true
new_object["widgets"][j]["cards"].push(object["widgets"][i]["cards"][0])
}
}
if (exist === false){
new_object["widgets"].push(object["widgets"][i])
}
}
console.log(new_object)
I have the following response from the server. I need to search this answer and compare it in turn with each field.
Example:
My task is that I know for sure that there should be 3 objects and each object has its own value for the type field, this is 'API', 'DEFAULT' or 'X'. How can you make it so that you can search for these three values in the whole object and get an error if one of them is missing?
{
"result": [
{
"id": "54270522",
"key": "1-16UUC93PT",
"type": "API"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "DEFAULT"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "Х"
}
],
"success": true
}
You can first verify that the length is 3 and then loop over all the types and check if each one is present.
const data = {
"result": [
{
"id": "54270522",
"key": "1-16UUC93PT",
"type": "API"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "DEFAULT"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "Х"
}
],
"success": true
};
const requiredTypes = ['API', 'DEFAULT', 'Х'];
const types = new Set(data.result.map(({type})=>type));
const good = data.result.length === 3 && requiredTypes.every(type=>types.has(type));
console.log(good);
In case you would like to also know which value of those 3 are missing:
const check = (obj) => {
if (obj.result.length !== 3) return false;
let validTypes = ['API', 'DEFAULT', 'X'];
obj.result.forEach((r) => {
const index = validTypes.indexOf(r.type);
if (index !== -1) validTypes.splice(index, 1);
})
if (validTypes.length) return `${validTypes.join(', ')} is missing`;
return true;
};
So if you would have something like:
const test = {
"result": [
{
"id": "54270522",
"key": "1-16UUC93PT",
"type": "API"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "DEFAULT"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "X2"
}
],
"success": true
}
and you call check(test) it will return "X is missing". If all three types are present in the object that gets passed into the check function, it will return true. Of course this can be adjusted as you need. More objects, different types etc...
This is a nested json file and I am trying to arrange it in a readable format to display in a table
I tried to manually put all the keys and values with in a for loop but there should be an elegant way to achieve this and hence I am reaching SO.
The actual JSON is quite a nested one and needed time to execute data with 500k rows
The result should be enhanced JSON with parent values appearing for child values as well
var property = {
"data": [{
"ID": "123456",
"name": "Coleridge st",
"criteria": [
{
"type": "type1",
"name": "name1",
"value": "7",
"properties": []
},
{
"type": "type2",
"name": "name2",
"value": "6",
"properties": [
{
"type": "MAX",
"name": "one",
"value": "100"
}, {
"type": "MIN",
"name": "five",
"value": "5"
}
]
},
{
"type": "type3",
"name": "name3",
"value": "5",
"properties": [{
"type": "MAX1",
"name": "one6",
"value": "1006"
}, {
"type": "MIN2",
"name": "five6",
"value": "56"
}]
}
]
},
{
"ID": "456789",
"name": "New Jersy",
"criteria": [
{
"type": "type4",
"name": "name4",
"value": "6",
"properties": [{
"type": "MAX12",
"name": "one12",
"value": "10012"
}, {
"type": "MIN23",
"name": "five12",
"value": "532"
}]
}
]
}]
};
var output = [];
property.data.forEach(function (users) {
var multirows = {
id: users.ID,
name: users.name,
};
for (var i = 0; i < users.criteria.length; i++) {
var criterias = {
type: users.criteria[i].type,
name: users.criteria[i].name,
value: users.criteria[i].value,
}
var mat_contacts_rows;
if (!isEmpty(users.criteria[i].properties)) {
for (var j = 0; j < users.criteria[i].properties.length; j++) {
var property = {
type: users.criteria[i].properties[j].type,
name: users.criteria[i].properties[j].name,
value: users.criteria[i].properties[j].value
};
mat_contacts_rows = { ...multirows, ...{ criteria: criterias }, ...{ properties: property } };
output.push(mat_contacts_rows);
}
} else {
var property = [];
mat_contacts_rows = { ...multirows, ...{ criteria: criterias }, ...{ properties: property } };
output.push(mat_contacts_rows);
}
}
});
console.log(JSON.stringify(output, undefined, 2))
function isEmpty(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key))
return false;
}
return true;
}
I think this could be a great exercise to you to don't answer your question but to give you some tips. You should first look at : Lodash wish has a bunch of usefull method to help you doing what you'r trying to do.
In a second time you should avoir using .forEach or for loops and try using Array.prototype.map or Array.prototype.reduce
I have the following JSON object. Using JQuery I need to find the values of the following:
summary.nameValues.ID and detail.TypedNameValues.size
Could somebody please show how this can be achieved using JQuery?
[
{
"path": "\\Users\\john.smith\\test",
"summary": {
"NameValues": [
{
"Name": "Id",
"Values": [
"232639"
]
},
{
"Name": "City",
"Values": [
"London"
]
}
]
},
"detail": {
"String": "some data",
"Result": 0,
"TypedNameValues": [
{
"Name": "name1",
"Type": "string",
"Value": "data here!!"
},
{
"Name": "size",
"Type": "long",
"Value": "434353"
}
]
}
}
]
jQuery doesn't work on plain object literals. You can use the below function in a similar way to search all 'id's (or any other property), regardless of its depth in the object:
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
}
Use like so:
getObjects(TestObj, 'id', 'A'); // Returns an array of matching objects
This answer taken from another thread. You may find more help here: use jQuery's find() on JSON object
Performing this kind of queries on JSON structures are trivial using DefiantJS (http://defiantjs.com). This lib extends the global object JSON with the method "search" - with which one can execute XPath expressive searches.
Check out this fiddle;
http://jsfiddle.net/hbi99/kLE2v/
The code can look like this:
var data = [
{
"path": "\\Users\\john.smith\\test",
"summary": {
"NameValues": [
{
"Name": "Id",
"Values": "232639"
},
{
"Name": "City",
"Values": "London"
}
]
},
"detail": {
"String": "some data",
"Result": 0,
"TypedNameValues": [
{
"Name": "name1",
"Type": "string",
"Value": "data here!!"
},
{
"Name": "size",
"Type": "long",
"Value": "434353"
}
]
}
}
],
res = JSON.search( data, '//*[Name="size"]' );
console.log( res[0].Value );
// 434353
Some one else as already answered, either way here is my version for the same.
<textarea id="ta" style="display:none;">[
{
"path": "\\Users\\john.smith\\test",
"summary": {
"NameValues": [
{
"Name": "Id",
"Values": [
"232639"
]
},
{
"Name": "City",
"Values": [
"London"
]
}
]
},
"detail": {
"String": "some data",
"Result": 0,
"TypedNameValues": [
{
"Name": "name1",
"Type": "string",
"Value": "data here!!"
},
{
"Name": "size",
"Type": "long",
"Value": "434353"
}
]
}
}
]</textarea>
Parser
var obj = $.parseJSON($('#ta').val());
var nameValues = obj[0].summary.NameValues;
var typedNameValues = obj[0].detail.TypedNameValues;
function getObjByName(o, name) {
for (var i = 0; i < o.length; i++) {
if (o[i].Name == name) {
return o[i];
}
}
return null;
}
alert(getObjByName(nameValues, 'Id').Values.join(", "));
alert(getObjByName(typedNameValues, 'size').Value);
A working fiddle for you on the same.
http://jsfiddle.net/3EVE4/