Javascript - Parsing JSON including int as Object - javascript

After several test and search, I can't find a way to navigate after parsing a JSON; here is the post-parsing result :
Object {documentation: "https://geocoder.opencagedata.com/api", licenses: Array[2], rate: Object, results: Array[1], status: Object…}
documentation
:
"https://geocoder.opencagedata.com/api"
licenses
:
Array[2]
rate
:
Object
results
:
Array[1]
0
:
Object
annotations
:
Object
components
:
Object
building
:
"C"
city
:
"Bordeaux"
country
:
"France"
country_code
:
"fr"
county
:
"Bordeaux"
postcode
:
"33000"
road
:
"Quai de Bacalan"
state
:
"Aquitaine"
suburb
:
"Bordeaux Maritime"
For example I can get the value of the response with the following code :
var locname = response.status.code;
But in the case there is a int as Object, like this :
var locname = response.results.0.formatted;
I have the following error :
Uncaught SyntaxError: Unexpected number
I try to escape the character, putting quote, etc but I couldn't find any solution.

in javascript, an object is also accessible as array, so for example, you have an object like this:
var obj = {name: 'Hans Yulian', age: 21, message: 'Handsome'};
obj[0] = 'This is an number index';
obj['message'] = 'Too Handsome';
all the key is accepted as long as they aren't something that contain special characters (-+=! etc) and not started with number. in any case you have the field that don't satisfy this exception, then you have to access it in array-way.
you can assign the value the same way as array, and also to get the content of that field.
in case you need to access something like
var locname = response.results.0.formatted;
Then the thing that you need is
var locname = response.results[0].formatted;
you can try make a html file with this content
<script>
var obj = {name: 'Hans Yulian', age: 21, message: 'Handsome'};
obj[0] = 'This is an number index';
obj['message'] = 'Too Handsome';
obj[1] = {};
obj[1].name = 'Handsome';
obj.handsome = [];
obj.handsome[0] = {};
obj.handsome[0].hansyulian = 'So Handsome';
console.log(obj);
console.log(obj[1].name);
console.log(obj.handsome[0].hansyulian);
</script>
and try see the console(right click, inspect element, select console for google chrome) to understand what happens there

Since results is an array you must use the following syntax:
var locname = response.results[0].formatted;
Instead of
var locname = response.results.0.formatted;

Related

Array as key and value but value is undefined

I don't know what's wrong with the code. it works fine and both array have data. but i don't understand why the output found undefined from var _city array as it passed data to the city field.
How can I fix this?
var city = {
_country : _city
};
I'm wondering what you read that made you possibly believe that by writing what you did you would magically have an object keyed with one array with values from a second...
Essentially what is happening when you did when you
var city = {
_country : _city
};
is create an object that looks like
var city = {
'_country' : ['your', 'array', 'of', 'cities']
};
that is to say, an object with one key, '_country' mapped to an array of cities.
This explains why you get undefined... city['any string that isn't exactly " _country"'] == undefined
What you want to do is more likely,
var city = _country.reduce(function(acc, cur, idx) { acc[cur] = _city[idx]; return acc; }, {});
It's because _country is already defined above:
var _country = ["Afghanistan","Bahrain","Canada","Denmark","Ethiopia","France","Germany","Hong Kong","India","Japan"];
Change the definition within city to something else (maybe country):
var city = {
country: _city,
};
And it'll work.

Angularfire 2 equalTo query not working with variable value obtained from native phone contacts

I'm using the following: Ionic 3, Angularfire 2, usb connected iphone & Safari Developer console for native cordova testing (for full context).
The goal is to run through the numbers retrieved from the phone contacts and see if they exist in any of the Firebase /users/~user id string~/ ..then later do things if they do.
The brief issue outline is that my approach is returning empty arrays for each number, as though the Angularfire equalTo query is not getting passed a value from the variable being fed into it.
Firebase structure
- users
- <user id string>
- name: "Some name"
- number: "1234 56789"
Exported JSON example (not real names or numbers):
"users" : {
"21JvDyuzNcbKTxGhCEyEzzSbwKc2" : {
"name" : "Gary Oose",
"number" : "1234 56789"
},
"F1AvstJCWqdzBWarXtxwcm01Ir02" : {
"name" : "Tina Urtle",
"number" : "987 654321"
},
"KNTJdnKaE3amJ79LOq40ztKWBWp2" : {
"name" : "Tommy Adpole",
"number" : "121 212 121"
}
}
The code is as follows..
contacts.find(["name", "phoneNumbers"], {multiple: true, hasPhoneNumber: true}).then(contacts => {
contacts.forEach((contact, index) => {
if (contacts[index].phoneNumbers !== null) {
var number_to_check = contacts[index].phoneNumbers[0].value;
//var number_to_check = contacts[index].phoneNumbers[0].value;toString();
//var number_to_check = "1234 56789";
console.log("contact_obj number = ", number_to_check);
let db_users_list = this.afDB.list(`/users/`,
{
query: {
orderByChild: 'number',
equalTo: number_to_check
}
}
).subscribe(number_matches => {
console.log('number_matches ', number_matches);
db_users_list.unsubscribe();
});
}
});
});
Running the above code
When either of the following lines are used:
var number_to_check = contacts[index].phoneNumbers[0].value;
or
var number_to_check = contacts[index].phoneNumbers[0].value.toString();
(the latter as I wasn't sure if the console output was lying to me that it was returning a string)
..the first console.log in the code confirms that a number has been returned from the native phone contacts, such as:
[Log] contact_obj number = - "1234 56789‬"
.. but the second console.log returns an empty array, as though nothing has matched against the Firebase DB in the query (.. it returns the same log for every number returned from the loop):
[Log] number_matches – [] (0)
The sanity check approach (..coffee's run out, I might be going mad)
When, instead of using either of the two lines above, I use the following line:
var number_to_check = "1234 56789";
(manually entering a static string value for the variable)
The first console.log returns the same number over and over, as expected seeing a static string value has been assigned to the number_to_check variable.
And the second console.log correctly returns an array for that number, indicating that the query has found a match for it in the Firebase DB, as seen below:
[Log] number_matches
Array (1)
0 {name: "Gary Oose", number: "1234 56789", $key: "21JvDyuzNcbKTxGhCEyEzzSbwKc2"}
So, does anyone have any pointers as to why the first approach (using the line of code below) is not working?
var number_to_check = contacts[index].phoneNumbers[0].value;
I get the feeling I'm missing something very obvious. Why would that changing variable not be getting picked up by the AngularFire equalTo query?
The issue is that there's sometimes whitespace in the string value the following line returns (from accessing the native phone's contact numbers):
contacts[index].phoneNumbers[0].value;
The solve is to remove the whitespace, like so:
contacts[index].phoneNumbers[0].value.replace(/\s/g, '');
Replace method found in a comment in Remove whitespaces inside a string in javascript
I imagine the whitespace being present in some but not all of the numbers must be down to how the phone stores the contact numbers when they are added in different ways.. i.e. via a shared contact, manual entry, etc).
With this solution in place I can successfully find the phone number matches (I also updated my Firebase number strings to be stored without spaces as well). As below..
"users" : {
"21JvDyuzNcbKTxGhCEyEzzSbwKc2" : {
"name" : "Gary Oose",
"number" : "123456789"
},
"F1AvstJCWqdzBWarXtxwcm01Ir02" : {
"name" : "Tina Urtle",
"number" : "987654321"
},
"KNTJdnKaE3amJ79LOq40ztKWBWp2" : {
"name" : "Tommy Adpole",
"number" : "121212121"
}
}
If I wanted to keep the spaces in the number strings, I could have added a single space in the replace() to account for that.. replace(/\s/g, ' ')

Length of and iterating array that is using custom properties

var profileDataCalls = [];
profileDataCalls['Profile'] = GetUserAttributesWithDataByGroup;
profileDataCalls['Address'] = GetUserAddresses;
profileDataCalls['Phone'] = GetUserPhoneNumbers;
profileDataCalls['Certs'] = GetUserCertifications;
profileDataCalls['Licenses'] = GetUserLicenses;
profileDataCalls['Notes'] = GetUserNotes;
My problem is the above JavaScript array is only a length of 0. I need an array that can be iterated over and holds the key(string) and value?
You want:
var profileDataCalls = {
'Profile' : GetUserAttributesWithDataByGroup,
'Address' : GetUserAddresses,
'Phone' : GetUserPhoneNumbers,
'Certs' : GetUserCertifications,
'Licenses' :GetUserLicenses,
'Notes' : GetUserNotes
};
Then you can access the values with, for example, profileDataCalls.profile or profileDataCalls[profile] (to retrieve whatever value is represented by the variable GetUserAttributesWithDataByGroup)
To iterate through the object, use:
for (var property in profileDataCalls) {
if (profileDataCalls.hasOwnProperty(property)) {
console.log(property + ': ' + profileDataCalls[property));
}
}
Javascript doesnt have associative arrays per say , what you are doing is adding properties to the Array instance. IE doint something like
profileDataCalls.Notes = GetUserNotes;
so you cant really use length to know how many properties your array would have.
now if your issue is iterating over your object properties , you dont need an array , just use an object :
profileDataCalls = {}
then use a for in loop to iterate over the keys :
for(var i in profileDataCalls ){
// i is a key as a string
if(profileDataCalls.hasOwnProperty(i)){
//do something with profileDataCalls[i] value , or i the key
}
}
it you have different requirements then explain it.
now the tricky part is profileDataCalls[0]="something" would be valid for an object({}), you would create a property only available through the lookup (obj[0]) syntax since it is not a valid variable name for javascript.
other "crazy stuffs" :
o={}
o[0xFFF]="foo"
// gives something like Object {4095:"foo"} in the console
Actually it also works like this:
var profileDataCalls = [{
Profile: GetUserAttributesWithDataByGroup(),
Address: GetUserAddresses(),
Phone: GetUserPhoneNumbers(),
Certs: GetUserCertifications(),
Licenses: GetUserLicenses(),
Notes: GetUserNotes()
}];
Then you can access the values with, for example, profileDataCalls[0].profile or profileDataCalls[0]["profile"].
To iterate through the object, you can use:
for (key in profileDataCalls[0]) {
console.log(profileDataCalls[0][key]);
}
Since this is an associative array, I never understood why people are saying its not possible in Javascript...in JS, everything is possible.
Even more, you could expand this array easily like this:
var profileDataCalls = [{
Profile: GetUserAttributesWithDataByGroup(),
Address: GetUserAddresses(),
Phone: GetUserPhoneNumbers(),
Certs: GetUserCertifications(),
Licenses:GetUserLicenses(),
Notes: GetUserNotes()
}{
Profile: GetUserAttributesWithDataByGroup(),
Address: GetUserAddresses(),
Phone: GetUserPhoneNumbers(),
Certs: GetUserCertifications(),
Licenses: GetUserLicenses(),
Notes: GetUserNotes()
}];
And access the array entries with profileDataCalls[0]["profile"] or profileDataCalls[1]["profile"] respectively.
What you want is an object:
Try
var profileDataCalls = new Object();
then reference your data as you do already.

Why does this Javascript example copy the variable value instead of pass by reference?

In Javascript The Good Parts, it states:
So I would expect the following code example to output 1001 since "objects are never copied but passed around by reference", so why does it output 0000?
var page_item = {
id_code : 'welcome',
title : 'Welcome',
access_groups : {
developer : '0010',
administrator : '0100'
}
};
page_item.access_groups.member = '0000';
var member = page_item.access_groups.member;
member = '1001';
$('p#test').html(page_item.access_groups.member); //should be "1001" but is "0000"
Added:
#Gareth #David, thanks, this is what I was trying to show in this example, works:
var page_item = {
id_code : 'welcome',
title : 'Welcome',
access_groups : {
developer : '0010',
administrator : '0100'
}
};
var page_item2 = page_item;
page_item2.access_groups.developer = '1001';
$('p#test').html(page_item.access_groups.developer); //is '1001'
Don't think of pass-by-reference in the C++ context, because it's not the same.
var member = page_item.access_groups.member // Sets member to this value
member = '1001'; // Now sets it to another value
If there was a method on strings which changed them, then this:
member.removeLastLetter();
would alter page_item.access_groups.member. However, with your = you are changing the variable's reference, not the object it previously referenced
Because page_item.access_groups.member is a string and not an Object.
This is probably getting bashed by JS-Gurus but basically it goes down like this:
Objects are passed by reference.
Strings (numbers, etc... basically 1 dimensional variables) are passed by value.
I did try and understand the lengthy explanations on data types but I seriously needed some work done and haven't gotten time to look at it more closely.

Search a JavaScript object

I have a JavaScript object like this:
[{
name : "soccer",
elems : [
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
},
{
name : "basketball",
elems : [
{name : "Dallas Mavericks"}
]
}]
Now I want to search on this JavaScript object in the browser. The search for "FC" should give me something like this:
[
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
How to do this fast? Are there any JavaScript libs for this?
You might like using jLinq (personal project)
http://hugoware.net:4000/Projects/jLinq
Works like LINQ but for JSON and it allows you to extend it and modify it however you want to. There is already a bunch of prebuilt methods to check values and ranges.
Seeing as though the only helpful answers have been referencing third party libraries - here's your native javascript solution. For anyone that only wants a few lines of code rather than a stack:
The function:
Array.prototype.findValue = function(name, value){
var array = map(this, function(v,i){
var haystack = v[name];
var needle = new RegExp(value);
// check for string in haystack
// return the matched item if true, or null otherwise
return needle.test(haystack) ? v : null;
});
return array;
}
A native .map() function:
map = function(array, mapFunction) {
var newArray = new Array(array.length);
for(var i = 0; i < array.length; i++) {
newArray[i] = mapFunction(array[i]);
}
return newArray;
}
Your object:
(skimmed from your posted abject):
myObject = {
name : "soccer",
elems : [
{name : "FC Barcelona"},
{name : "Liverpool FC"}
]
},
{
name : "basketball",
elems : [
{name : "Dallas Mavericks"}
]
}
For usage:
(This will search your myObject.elems array for a 'name' matching 'FC')
var matched = myObject.elems.findValue('name', 'FC');
console.log(matched);
The result - check your console:
[Object, Object, findValue: function]
0: Object
name: "FC Barcelona"
__proto__: Object
1: Object
name: "Liverpool FC"
__proto__: Object
length: 2
__proto__: Array[0]
Try jOrder. http://github.com/danstocker/jorder
It's optimized for fast O(logn) search and sorting on large (thousands of rows) tables in JS.
As opposed to array iteration, which most of the answers here are based on, jOrder uses indexes to filter data. Just to give you an idea, free-text search on a 1000-row table completes about 100 times faster than iteration. The bigger the table, the better ratio you get.
However jOrder can't process the format of your sample data. But if you re-format it like this:
var teams =
[
{ sport : "soccer", team: "FC Barcelona" },
{ sport : "soccer", team: "Liverpool FC" },
{ sport : "basketball", team : "Dallas Mavericks"}
]
You can get the desired results by first setting up a jOrder table:
var table = jOrder(teams)
.index('teams', ['team'], { grouped: true, ordered: true, type: jOrder.text });
And then running a search on it:
var hits = table.where([{ team: 'FC' }], { mode: jOrder.startof });
And you'll get exactly the two rows you needed. That's it.
The straightforward way to do this is simply to iterate over every property of the object and apply a test function to them (in this case, value.contains("FC")).
If you want it to go faster, you'd either need to implement some kind of caching (which could be eagerly populated in the background ahead of any queries), or perhaps precalculate the result of various popular test functions.
You could do this with regular expressions performed against a serialized JSON string:
var jsonString = "[{ name : \"soccer\", elems : [ {name : \"FC Barcelona\"}"
+", {name : \"Liverpool FC\"}]},{name : \"basketball\",elems : ["
+"{name : \"Dallas Mavericks\"} ]}]";
var pattern = /\s*([\w\d_]+)\s*:\s*((\"[^\"]*(your pattern here)[^\"]*\")|(\'[^\']*(your pattern here)[^\']*\'))\s*/g;
var foundItems = [];
var match;
while(match = pattern.exec(jsonString)){
foundItems.push(match[0]);
}
var foundJSON = "[{" + foundItems.join("}, {") + "}]";
var foundArray = eval(foundJSON);
I haven't tested the loop part of this, but the Regex seems to be working well for me with simple tests in firebug.
In regards to AngularJS, you can do this:
var item = "scope-ng-model";
(angular.element('form[name="myForm"]').scope())[item] = newVal;

Categories