Unable to get the length of JSON object - json

I am getting 'TypeError: Cannot convert undefined or null to object' while trying to access the length of json object in nodejs.
Following is how my data looks like:
{
"college": [
{
"colleges": [],
"department": [
1,
2,
3
],
"general_course": [],
"id": 1,
"name": "College of the Arts",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1919"
},
{
"colleges": [],
"department": [
4,
5,
6
],
"general_course": [],
"id": 2,
"name": "College of Communications",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1920"
},
{
"colleges": [],
"department": [
7,
12
],
"general_course": [],
"id": 3,
"name": "College of Education",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1921"
},
{
"colleges": [],
"department": [
13,
17,
19
],
"general_course": [],
"id": 4,
"name": "College of Engineering and Computer Science",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1922"
},
{
"colleges": [],
"department": [
20,
26,
27
],
"general_course": [],
"id": 5,
"name": "College of Health and Human Development",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1923"
},
{
"colleges": [],
"department": [
28,
29,
32,
48
],
"general_course": [],
"id": 6,
"name": "College of Humanities and Social Sciences",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1924"
},
{
"colleges": [],
"department": [
52,
57
],
"general_course": [],
"id": 7,
"name": "College of Natural Sciences and Mathematics",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1925"
},
{
"colleges": [],
"department": [
58,
59,
63
],
"general_course": [],
"id": 8,
"name": "Mihaylo College of Business and Economics",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1926"
}
]
}
Step 1 - Parsing it into nodejs:
let colleges = JSON.parse(data)
Step 2 - Saving it into the dialogflow app data:
app.data.collegeData = data;
Step 3 - Accessing the length:
let collegeLength = Object.keys(app.data.collegeData.college).length;
Getting following error in firebase console:
TypeError: Cannot convert undefined or null to object
Update:
Here is the code:
if ( app.data.collegeData === undefined ){
app.data.collegeData = [];
}
**Step 1 =>**
showColleges(college);
**Step 2 =>**
function showColleges(collegeName){
if (app.data.collegeData.length === 0){
getCollegeData().then(buildSingleCollegeResponse(collegeName))
.catch(function (err){
console.log('No college data')
console.log(err)
});
}
else{
buildSingleCollegeResponse(collegeName);
}
}
**Step 3 =>**
function getCollegeData(){
console.log('Inside get College Data')
return requestAPI(URL)
.then(function (data) {
let colleges = JSON.parse(data)
if (colleges.hasOwnProperty('college')){
saveData(colleges)
}
return null;
})
.catch(function (err) {
console.log('No college data')
console.log(err)
});
}
**Step 4 =>**
function saveData(data){
app.data.collegeData = data;
console.log(app.data.collegeData)
}
**Step 5 =>**
function buildSingleCollegeResponse(collegeName){
let responseToUser, text;
//console.log('Data is -> '+ Object.keys(app.data.collegeData.college).length);
//console.log('Length is -> '+ app.data.collegeData.college.length);
console.log('Count is -> '+app.data.collegeCount);
let collegeLength = Object.keys(app.data.collegeData.college).length;
if ( collegeLength === 0){
responseToUser = 'No colleges available at this time';
text = 'No colleges available at this time';
}
else if ( app.data.collegeCount < collegeLength ){
for ( var i = 1; i <= collegeLength; i++)
{
console.log('All Colleges:: '+app.data.collegeData.college[i])
let coll = app.data.collegeData.college[i]
let name = coll.name
console.log('checkCollegeExist => College Name:: '+ name)
console.log('checkCollegeExist => Parameter => College Name:: '+collegeName)
if(String(name).valueOf() === String(collegeName).valueOf()){
responseToUser = 'Yes! CSUF has '+collegeName;
text = 'Yes! CSUF has '+collegeName;
}else{
responseToUser = 'CSUF does not teach ' +collegeName+' currently';
text = 'CSUF does not teach ' +collegeName+' currently';
}
}
}
else{
responseToUser = 'No more colleges';
}
if (requestSource === googleAssistantRequest) {
sendGoogleResponse(responseToUser);
} else {
sendResponse(text);
}
}

This is the culprit:
getCollegeData().then(buildSingleCollegeResponse(collegeName))
That calls buildSingleCollegeResponse(collegeName) and then passes its return value into then, just like foo(bar()) calls bar and passes its return value into foo.
You wanted to pass a functon to then:
getCollegeData().then(() => buildSingleCollegeResponse(collegeName))
// An arrow function ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that now that it's clear from the updated question that app.data.collegeData.college is an array, there's no need for Object.keys. Change:
let collegeLength = Object.keys(app.data.collegeData.college).length;
to simply
let collegeLength = app.data.collegeData.college.length;
Arrays have a length property (whereas non-array objects don't, by default).

You haven't mentioned what value app.data holds before issuing app.data.collegeData = data;
If app.data is undefined you should try app.data = {collegeData: data}
Or else negating what app stores. Following works
app = {};
app.data = {};
app.data.collegeData = data;
app.data.collegeData.college.length
You don't need to do the following
let collegeLength = Object.keys(app.data.collegeData.college).length;
Update: Refer to https://jsfiddle.net/dmxuum79/3/

Related

Getting inventory contexts of Steam users

A stack overflow answer explains how to retrieve a user's public inventory
http://steamcommunity.com/profiles/<PROFILEID>/inventory/json/<APPID>/<CONTEXTID>
I read that context ID must be set as 2 to find items for most games, but this is not always the case. Is there any official API to find a user's inventory contexts? steamapis.com already has a paid API which performs this task:
{
"steamID": {
"universe": 1,
"type": 1,
"instance": 1,
"accountid": 78261062
},
"name": "PEPZ",
"onlineState": "online",
"stateMessage": "Online",
"privacyState": "public",
"visibilityState": "3",
"avatarHash": "5b702b331ddeb928225ad562a3e729aecd191b9a",
"vacBanned": false,
"tradeBanState": "None",
"isLimitedAccount": false,
"customURL": "pepzwee",
"memberSince": "2011-02-21T22:00:00.000Z",
"location": "Estonia",
"realName": "SteamApis.com Developer",
"summary": "",
"groups": [
{
"universe": 1,
"type": 7,
"instance": 0,
"accountid": 28077004
},
...
],
"primaryGroup": {
"universe": 1,
"type": 7,
"instance": 0,
"accountid": 28077004
},
"contexts": {
"440": {
"appid": 440,
"name": "Team Fortress 2",
"icon": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/440/e3f595a92552da3d664ad00277fad2107345f743.jpg",
"link": "http://steamcommunity.com/app/440",
"asset_count": 11,
"inventory_logo": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/440/e613d1d46de26ea755105b898cc8830d305353f3.png",
"trade_permissions": "FULL",
"load_failed": 0,
"rgContexts": {
"2": {
"asset_count": 11,
"id": "2",
"name": "Backpack"
}
}
},
...
}
}
Where "rgContexts" contains inventory context for each game.
I found out with some inspect element work, that there is a script tag available with the exact information you need. This is an example of my profile:
var g_rgWalletInfo = {"success":false};
var g_bInventoryIsInModalDialog = false;
var g_bIsInMarketplace = false;
UserYou.SetSteamId( '76561199033382814' );
var g_rgAppContextData = {"753":{"appid":753,"name":"Steam","icon":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/753\/135dc1ac1cd9763dfc8ad52f4e880d2ac058a36c.jpg","link":"https:\/\/steamcommunity.com\/app\/753","asset_count":303,"inventory_logo":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/753\/db8ca9e130b7b37685ab2229bf5a288aefc3f0fa.png","trade_permissions":"FULL","load_failed":0,"store_vetted":"1","rgContexts":{"6":{"asset_count":303,"id":"6","name":"Community"}}},"730":{"appid":730,"name":"Counter-Strike: Global Offensive","icon":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/730\/69f7ebe2735c366c65c0b33dae00e12dc40edbe4.jpg","link":"https:\/\/steamcommunity.com\/app\/730","asset_count":61,"inventory_logo":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/730\/3ab6e87a04994b900881f694284a75150e640536.png","trade_permissions":"FULL","load_failed":0,"store_vetted":"1","rgContexts":{"2":{"asset_count":61,"id":"2","name":"Backpack"}}}};
var g_strInventoryLoadURL = 'https://steamcommunity.com/id/stoplookingatmyid/inventory/json/';
$J( function() {
UserYou.LoadContexts( g_rgAppContextData );
} );
$J( function() {
var bHasPendingGifts = false;
InitInventoryPage( bHasPendingGifts, -1, false );
});
var g_bInClient = false;
var g_bInChinaRealm = false;
var g_bViewingOwnProfile = false;
var g_bMarketAllowed = false;
var g_strLanguage = 'english';
var g_strCountryCode = "US";
var g_strProfileURL = 'https://steamcommunity.com/id/stoplookingatmyid';
Some of this data is junk, but g_rgAppContextData is exactly what you need in JSON format, and it just needs to be parsed if your programming language of choice. In this example, 753 is the app id of Steam, with 6 being the context id, and 730 is CSGO'S app id, with 2 as the context id. with This data won't be present if the user has a private steam inventory.

Show product.length when I have JSON / OBJ / JSON / OBJ / JSON

I have this JSON
{
"StatusCode": 0,
"StatusMessage": "OK",
"StatusDescription": [
{
"_id": "12123",
"dateCreated": "2019-12-03T13:45:30.418Z",
"pharmacy_id": "011E752345553380ABC13FFA163ECD15"
"products": [
{
"productID": "1",
"quantity": 3,
"product_name": "BETADINE",
"price": 10
},
{
"productID": "2",
"quantity": 1,
"product_name": "EUCARBON",
"price": 10
}
]
},
{
"_id": "56233",
"dateCreated": "2019-12-04T09:55:21.555Z",
"pharmacy_id": "011E762345552280FBC13FFA163ECD10"
"products": [
{
"productID": "44",
"quantity": 1,
"product_name": "BETADINE",
"price": 10
}
]
}
]
}
In this JOSN I want to get length of products. For example in this I have 2 pharmacy and 5 products. I want to show 5 in my shop cart.
So I get this JSON from API with this function:
public cart: Shop[];
cartlength: number;
ngOnInit(): void {
this.shopservice.getShoppingCart().subscribe(
cart => {
this.cart = cart;
this.cartlength = cart.length;
},
err => console.error('errorrrrrrr', err),
() => console.log('error')
);
}
IN HTML:
<ActionItem ios.systemIcon="9" ios.position="left" android.position="actionBar" [text]='cartlength'></ActionItem>
Any idea please?
If cart is the array containing all the pharmacies you could use reduce method to determine the total quantity of all products for each pharmacy.
this.cartlength = this.cart.reduce((count, pharmacy) => {
count += pharmacy.products.reduce((totalQty, product) => {
return totalQty += product.quantity;
}, 0)
return count;
}, 0)

access value in array from Json response typesciprt

How can i access subjects in Json response and take the value which in types using typescript ?
Json Response :
{
"$id": "1",
"Council_ID": 102,
"place": "bla bla bla",
"number": "4644",
"type": 2,
"user_Id": 15,
"subjects": [
{
"$id": "2",
"subjectCode": "464",
"type": 1,
"branch": "cairo",
"gender": true
},
{
"$id": "3",
"subjectCode": "466",
"type": 5,
"branch": "alex",
"gender": true
}
],
"absence": []
}
meeting.component.ts :
this.dataStorageService.getCouncilId(this.meetingID).subscribe(response => {
this.subjectsWithID = response.json();
console.log(this.subjectsWithID, 'All Response')
this.typee = this.subjectsWithID.subjects.type;
console.log(this.typee, 'bla bla');
});
Here is how to access the values
this.subjectsWithID.Council_ID; // 102
this.subjectsWithID.type; // 2
this.subjectsWithID.$id; // '1'
this.subjectsWithID.subjects[0].$id; // '2'
this.subjectsWithID.subjects[0].type; // 1
this.subjectsWithID.subjects[1].$id; // '3'
this.subjectsWithID.subjects[1].type; // 5
I might have misunderstood your question. If so please provide some example of the desired output.
this.dataStorageService
.getCouncilId(this.meetingID)
.map(json)
.map(response => response.subjects.map(subject => subject.type))
.subscribe(response => { ... });

Remove proxies from Json Response Symfony2

I'm working in Symfony2 application and what I'm trying to do is to remove unwanted fields from response and show only fields that I want.
My JSON looks like this:
[
{
"id": 1,
"title": "Granit",
"typeId": {
"id": 1,
"name": "X or Y",
"acroname": "xory",
"__initializer__": null,
"__cloner__": null,
"__isInitialized__": true
},
"pushDate": {
"timezone": {
"name": "Europe/Berlin",
"location": {
"country_code": "DE",
"latitude": 52.5,
"longitude": 13.36666,
"comments": "most locations"
}
},
"offset": 7200,
"timestamp": 1460584800
},
"addedAt": {
"timezone": {
"name": "Europe/Berlin",
"location": {
"country_code": "DE",
"latitude": 52.5,
"longitude": 13.36666,
"comments": "most locations"
}
},
"offset": 7200,
"timestamp": 1460548644
},
"deviceToShow": {
"id": 2,
"name": "Mobile",
"__initializer__": null,
"__cloner__": null,
"__isInitialized__": true
},
"statusSurvey": false,
"slides": [
{
"id": 1,
"title": "First Question",
"picture1": "160413015724bazinga2.jpg",
"picture2": "160413015724th.jpg",
"idSurvey": 1,
"absolutePathpic1": "C:\\xampp\\htdocs\\stu-wrapper\\src\\AppBundle\\Entity/../../../web/uploads/slideSurvey/160413015724bazinga2.jpg",
"webPathpic1": "uploads/slideSurvey/160413015724bazinga2.jpg",
"absolutePathpic2": "C:\\xampp\\htdocs\\stu-wrapper\\src\\AppBundle\\Entity/../../../web/uploads/slideSurvey/160413015724th.jpg",
"webPathpic2": "uploads/slideSurvey/160413015724th.jpg",
"file": null,
"file1": null
}
],
"categories": []
}
]
I want to remove fields like "initializer": null,"cloner": null, "isInitialized": true and hide timezone object and show only "timestamp".
Here is my controller where I'm doing serializing and creating Json Response.
public function getAction()
{
$em = $this->getDoctrine ()->getManager ();
$survey = $em->getRepository ( 'AppBundle:Survey' )->findAll ();
if ( !$survey ) {
throw $this->createNotFoundException ( 'Data not found.' );
}
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer();
$normalizer->setCircularReferenceHandler ( function ( $survey ) {
return $survey->getid ();
} );
$serializer = new Serializer( array ( $normalizer ), array ( $encoder ) );
$jsonContent = $serializer->serialize ( $survey, 'json' );
return new Response( $jsonContent );
}
Thank you.
Try to exclude this fields:
$normalilzer->setIgnoredAttributes(
[
"__initializer__",
"__cloner__",
"__isInitialized__"
]);
Detach entity to remove doctrine2 links to the object
$em->detach($survey);

How to chain sql queries which are dependent on each other in node

I am looking to fetch data from on query and then run a array loop over a item stored in result. then Fetch data from another query using keys from the array fetched from first query.
What ever I have tried is not giving me the desired result as array loops runs out before the sql queried finishes and produce the desired result.
I have tried solution with async.series function and async.map function but result is not coming in the desired sequence.
This is the output From first query.
My objective is to add array of option details in place option id which is returned from first query.
[
{
"id": 318,
"name": "Sandwich Dosa",
"price": 140,
"option": ''
},
{
"id": 319,
"name": "Spi. Prem Uttappa",
"price": 131,
"option": '1,2'
},
{
"id": 320,
"name": "Paneer Spl. Prem Uttappa",
"price": 140,
"option": ''
},
{
"id": 321,
"name": "Spl. Spicy Uttappa",
"price": 131,
"option": ''
}
]
Looking to build as
[
{
"id": 318,
"name": "Sandwich Dosa",
"price": 140,
"option": ''
},
{
"id": 319,
"name": "Spi. Prem Uttappa",
"price": 131,
"option": [{
id:'1',
name:'Regular',
price:'89',
},
{
id:'2',
name:'Spicy',
price:'119',
}]
},
{
"id": 320,
"name": "Paneer Spl. Prem Uttappa",
"price": 140,
"option": ''
},
{
"id": 321,
"name": "Spl. Spicy Uttappa",
"price": 131,
"option": ''
}
]
This is my current code through which I am trying to achive
var data = {
"error": 1,
"items": ""
};
connection.query("SELECT * FROM items WHERE status=1 AND menu_grp_id=" + req.params.sid, function(err, rows, fields) {
var items = []; // temporary holder for items
if(err) { throw err } else {
if(rows.length != 0) {
for (var key in rows) {
// Holding Item properties
var item = {
id: '',
name: '',
price: '',
option: ''
};
item.id = rows[key].id;
item.name = rows[key].item_name;
item.price = rows[key].price;
item.option = rows[key].option;
items.push(item); // pushing item object into items array
}
data["error"] = 0;
data['items'] = items;
if((data['items'].length > 0)) {
for(i = 0; i < data['items'].length; i++) {
if(data['items'][i].option == "") {
data['items'][i].option = [];
} else {
var array = data['items'][i].option.split(",")
data['items'][i].option = array;
}
}
}
res.json(data); // sending JSON Data
} else {
data["error"] = 0;
data["items"] = 'No item Found..';
res.json(data); // sending JSON Data
}}
});
Probably I'm a bit late here, but I think that async.waterfall is what you need.
async.waterfall([
function(cb){
connection.query("SELECT * FROM items WHERE status=1 AND menu_grp_id=" + req.params.sid, function(err, rows, fields) {
//manipulate your data as you wish
data = synchronousManipolutionOfYourData();
cb(null, data);
});
},
function(data, cb){
//data here stores the data you passed as a second parameter in the preciding callback
//execute your second query with the data you got from the first query.
cb(null, dataManipulatedAfterSecondQuery)//and so on
},
//other functions if you need other queries
], function(){
done;
});