I have a Json array which has the elements below:
"adjacencies", "data", "id", "name".
In some elements, "adjacencies" does not exist.
This is an example:
var JsonArray = [
{
"id" : "id1",
"name" : "name1",
"data" : {
"$type" : "circle",
"$color" : "#AEC43B"
}
}, //Without "adjacencies"
{
"id" : "id2",
"name" : "name2",
"data" : {
"$type" : "circle",
"$color" : "#AEC43B"
}
}, //Without "adjacencies"
{
"adjacencies": [
{
"nodeTo": "id1",
"nodeFrom": "id3",
"data": {
"$color": "#416D9C"
}
}
],
"id" : "id3",
"name" : "name3",
"data" : {
"$type" : "circle",
"$color" : "#AEC43B"
}
} //With "adjacencies"
];
The first and the second elements doesn't contain "adjacencies", but the third element does.
In the loop for (i = 0; i < JsonArray.length; i++) how do I access the third element?
Is there a .contain property for example?
Thanks in advance:)
One way to do it is by checking if the value is of type undefined:
for (i = 0; i < JsonArray.length; i++) {
var item = JsonArray[i];
if (typeof item.adjacencies !== "undefined") {
// item has adjacencies property
}
}
As an aside: this is not a JSON array -- it's a Javascript array. There are no JSON objects, no JSON arrays, no JSON nothing. The only JSON-y thing that exists is plain JSON, which is a serialization format.
use hasOwnProperty
So you can do this
for (i = 0; i < JsonArray.length; i++){
if( JsonArray[i].hasOwnProperty('adjacencies') ){
//Do something here
}
}
Related
I am trying to remove the empty object {} from the below structure.
data = [{
"total" : "value",
"status" : "statusVal",
"recs" : [{
"total" : "value",
"region" : "name",
"recs" : [{},{
"recs" : [{
"recs" : [{
"value" : "a",
"label" : "fn"
}]
}]
}]
}]
}]
This is my JavaScript code where I process the data and trying to remove the empty object from the result.
var result = json.parse(data);
for(var i=0;i<result.length;i++){
if(result[i].hasOwnProperty("recs")){
var fset = result[i].recs;
for(var j=0;j<fset.length;j++){
if(fset[j].recs === undefined || fset[j].recs === null){
delete fset[j].recs;
}
if(fset[j].hasOwnProperty("recs")){
var sset = fset[i].recs;
for(var k=0;k<sset.length;k++){
var tset = sset[i].recs;
if(sset[k].hasOwnProperty("recs")){
for(var z=0;z<tset.length;z++){
if(tset[z].hasOwnProperty("recs")){
// logic to push
}
}
}
}
}
}
}
}
I tried checking null and undefined and also with property check bool as false. Since the empty {} is always returning length as 1, that is also ruled out. I am stuck here on processing the removal of empty object.
Above code is removing the entire recs node. Can you help me find what I am missing?
Check the length of the Object.keys() to see if object is empty or not.
Object.keys(fset[j].recs).length === 0
You can't iterate all the dynamic levels of array manually, so better to write the function which has recursive function call.
var data = [{
"total": "value",
"status": "statusVal",
"recs": [{
"total": "value",
"region": "name",
"recs": [{}, {
"recs": [{
"recs": [{
"value": "a",
"label": "fn"
}]
}]
}]
}]
}]
function removeEmpty(ary) {
ary.forEach((item, index) => {
if (Object.keys(item).length === 0) { ary.splice(index, 1); }
else if (item.recs && item.recs.length > 0)
removeEmpty(item.recs)
});
}
removeEmpty(data)
console.log(data)
I want to write a utility which connects to a REST api downloads data in JSON format and then paints the data as nested tables using Bootstrap.
JSON Data -
[
{
"id" : "Id1",
"name" : "Name1",
"orders" : [{"orderId" : "o1", "size" : 34}, {"orderId" : "o2", "size" : 3}]
},
{
"id" : "Id2",
"name" : "Name2",
"orders" : [
{"orderId" : "o3", "size" : 5, "addresses" : [{"addressId" : "a1", "phone" : "1235"}, {"addressId" : "a2", "phone" : 555}]},
{"orderId" : "o4", "size" : 5, "addresses" : [{"addressId" : "a3", "phone" : "1235"}]}
]
}
]
I looked at the sub-table feature of Bootstrap, however it seems that it would need lot of custom code to get this working. Is there a better way to bind the json to table in a generic way?
Edit
After spending some time I was able to achieve this -
As you can see, I could get one level of nesting, however i just need to go one level deep. Any suggestions?
<script>
var $table = $('#table')
function buildTable($el, jsonData) {
var i; var j; var row
var columns = []
var data = []
if(!Array.isArray(jsonData) && jsonData.length == 0) {
return;
}
Object.keys(jsonData[0]).forEach( (k) => {
columns.push({
field: k,
title: k,
sortable: true
})
})
for(var j = 0; j < jsonData.length; j++) {
row = {}
Object.keys(jsonData[j]).forEach( (k) => {
row[k] = jsonData[j][k]
})
data.push(row)
}
$el.bootstrapTable({
columns: columns,
data: data,
detailFilter: function (index, row) {
console.log("detail filter " + Object.values(row))
for(var k in row) {
if(Array.isArray(row[k])){
return true;
}
}
return false;
},
onExpandRow: function (index, row, $detail) {
console.log("expand row keys " + Object.keys(row))
console.log("expand row vals " + Object.values(row))
var newRow = {};
for(var k in row) {
if(Array.isArray(row[k])){
alert('found ' + row[k])
newRow = row[k]
break
}
}
buildTable($detail.html('<table></table>').find('table'), newRow)
}
})
};
var mydata =
[
{
"id": 0,
"name": "test0",
"price": "$0",
"orders" :
[
{
"name" : "ABC",
"size" : 25,
"someList": [{"a":1, "b":2}, {"a":3, "b":4}]
},
{
"name" : "XYZ",
"size" : 50
}
]
}
/* {
"id": 1,
"name": "test1",
"price": "$1"
},
{
"id": 2,
"name": "test2",
"price": "$2",
"orders" : [{"name" : "def", "size": 45}]
}*/
];
$(function() {
buildTable($table, mydata)
})
I have this json file:
test.json:
{"rows" : [
{"key": "value"},
{"key": "value"}
]
}
I tried this code to read it:
var json = require('test.json');
for (var row in json.rows) {
console.log(row.key);
}
it prints:
/usr/local/bin/node json-parser.js
undefined
undefined
What am I doing wrong?
Where row is the variable holding property name not the object, so you need to retrieve it using the property name ( Refer : for...in loop documentation). In your case it will be the index of array. There is no need to use for...in iterator here, a simple for loop is enough.
for (var row in json.rows) {
console.log(json.rows[row].key);
}
var json = {
"rows": [{
"key": "value"
}, {
"key": "value"
}]
};
for (var row in json.rows) {
console.log(json.rows[row].key);
}
With a simple for loop
for (var i=0;i < json.rows.length; i++) {
console.log(json.rows[i].key);
}
var json = {
"rows": [{
"key": "value"
}, {
"key": "value"
}]
};
for (var i = 0; i < json.rows.length; i++) {
console.log(json.rows[i].key);
}
Since the property holds an array useArray#forEach method to iterate.
json.rows.forEach(function(v){
console.log(v.key);
}
var json = {
"rows": [{
"key": "value"
}, {
"key": "value"
}]
};
json.rows.forEach(function(v) {
console.log(v.key);
})
I am using d3.js's "d3.json(); function to reach out and fetch some data from a REST API.
The data comes back as this:
{
"offset" : 0,
"rows": [
{ "_id":
{ "$oid" : "1234567" },
"mockupData" : [ {
"Analysis" : "Test",
"Description" : "The Test indicates...",
"Data" : [
{ "Category" : "A",
"Statistic" : 0.15,
"Value" : 0.95 },
{ "Category" : "B",
"Statistic" : 0.65,
"Value" : 0.85 },
] } ] }
],
"total_rows" : 1 ,
"query" : {} ,
"millis" : 0
}
I am having an extremely difficult time drilling down in to the json to get what I want.
I'm attempting to set it up like this:
function generateChart(){
var chart;
var Category = [{key:"Stuff", values:[]}];
d3.json('http://url_that_returns_json/', function(error,data{
for(var key in data._SOMETHING_){
switch(key){
case "A":
Category[0] ["values"].push({"label":"Statistic","value""data.Category[key]});
... // same for B
})
// more graph logic
I appear to be missing some entire fragment of knowledge on this. Guidance? Help?
Thanks in advance.
Here is a fiddle I have implemented : https://jsfiddle.net/thatOneGuy/486mwb86/1/
First off, I set the data as a variable so I can use it later. So :
var data = {
"offset": 0,
"rows": [{
"_id": {
"$oid": "1234567"
}, ... //and so on
This is exactly the same as you using :
d3.json('http://url_that_returns_json/', function(error,data{
Both data variables are the same.
Then I got to the point you wanted to check, i.e the categories in the data attribute, like so :
var thisDataSet = data.rows[0].mockupData[0].Data;
As this is an array and not an object, I used a for loop to loop through :
for (var i = 0; i < thisDataSet.length; i++) {
And, in my opinion, you didn't need a switch statement as it looks like you just wanted to populate Category.values with the different categories. So I just pushed the current value of the category in the dataset to this Category.values :
Category[0]["values"].push({
"label": "Statistic",
"value": thisDataSet[i].Category //push category here
});
And that's it. Check the console log for output. Should work fine. Full function :
function generateChart() {
var chart;
var Category = [{
key: "Stuff",
values: []
}];
console.log(data.rows[0].mockupData[0].Data)
var thisDataSet = data.rows[0].mockupData[0].Data;
for (var i = 0; i < thisDataSet.length; i++) {
//for (var key in data.rows[0].mockupData[0].Data) {
console.log(thisDataSet[i])
Category[0]["values"].push({
"label": "Statistic",
"value": thisDataSet[i].Category
});
}
console.log(Category)
}
I have two data structures with different shapes that come from two different API's. The data is in JSON format, language is JavaScript.
Array 1:
[ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" },
{ "html" : "some_html", "name" : "TASK_NAME_2" } ] },
{ "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" },
{ "html" : "some_html", "name" : "TASK_NAME_4" } ] }]
Array 2:
[ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" },
{ "name" : "TASK_NAME_2", "status" : "OPEN" } ],
[ { "name" : "TASK_NAME_3", "status" : "OPEN" },
{ "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ]
The elements of the tooltips field from the array 1 contain the same "name"s as elements of array 2. How can I elegantly merge "status" from the array 2 into tooltips within array 1?
I thought that lenses could be the right answer, but I'm unsure as I've never used them.
I am aware of some ways I could solve it using nested iteration and updating array 1. I am ideally looking for an approach that doesn't modify existing data structures.
This is little complex but it should work for you
array2.forEach(function(tooltips){
tooltips.forEach(function(tooltip){
for (var i = 0; i < array1.length; i++) {
for (var j = 0; j < array1[i].tooltips.length; j++) {
var arr1Tooltip = array1[i].tooltips[j];
if(arr1Tooltip.name == tooltip.name)
arr1Tooltip.status = tooltip.status;
};
};
});
});
console.log(JSON.stringify(array1));
This is probably way over engineered and not very efficient, but you can do it as with this JSFiddle using recursive functions. I'm too tired to do it in a clever way.
var arr1 = [ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" },
{ "html" : "some_html", "name" : "TASK_NAME_2" } ] },
{ "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" },
{ "html" : "some_html", "name" : "TASK_NAME_4" } ] }];
var arr2 = [ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" },
{ "name" : "TASK_NAME_2", "status" : "OPEN" } ],
[ { "name" : "TASK_NAME_3", "status" : "OPEN" },
{ "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ];
var findStatus = function(name, searchArray) {
var r = '';
if (typeof searchArray === 'object') {
if ("name" in searchArray && "status" in searchArray) {
if (searchArray.name == name) {
return searchArray.status;
} else {
return '';
}
} else {
for (var i in searchArray) {
r = findStatus(name, searchArray[i]);
if (r != '') {
return r;
}
}
}
}
return '';
};
var updateStatus = function(arrToUpdate, arrWithStatus) {
var copy = $.extend(true, {}, arrToUpdate);
var r = '';
if (typeof copy === 'object') {
if ("name" in copy) {
r = findStatus(copy.name, arrWithStatus);
if (r != '') {
copy.status = r;
}
} else {
for (var i in copy) {
copy[i] = updateStatus(copy[i], arrWithStatus);
}
}
}
return copy;
};
var arr3 = updateStatus(arr1, arr2); // Final combined array
I added the var copy = $.extend(true, {}, arrToUpdate); line so that it will do a deep copy and not modify the original array, as a result, it requires jQuery.
Since your data structure is nested, you will need two zip.map/zipWiths:
zip(array1, array2).map(function([obj, tooltips]) { // ES6 destructuring syntax
return {
document: obj.document,
tooltips: zip(obj.tooltips, tooltips).map(function([tooltip, extender]) {
return {
html: tooltip.html,
name: tooltip.name,
status: extender.status
};
})
};
})
If you don't like to repeat those object literal structures, you might be able to use some copying function; for example
extend({}, document, {tooltips:…})
extend({}, tooltip, extender);
You also might use a lenses library like https://github.com/DrBoolean/lenses or https://github.com/fantasyland/fantasy-lenses for that, but I'm not sure whether that's worth the effort - the above code only needs underscore/lodash.
To get around the inner zipWith, you would need a Traversal lens (I assume you're familiar with this article), but I haven't yet seen a JavaScript library that offers such.