Iterate only through objects - php

I am receiving some JSON from PHP like this (previewed in Firefox tools):
1:Object
0:Object
1:Object
2:Object
3:Object
Name: "SomeName"
I now want to iterate through the objects, but not the Name key. It seems if I do an $.each it includes the key/value pair. How can I avoid it? Also why can I choose a numerical value for the first Object (I have it "1") but not assign a value to it? I wish it could look like this for example
1:SomeNameIGaveIt
0:Object
1:Object
2:Object
3:Object
That would make my Name k/v pair obsolete.
JSON
{"1": {"Name":"SomeName", "0":{"data":"data"}. "1":{"data":"data"}}}

In JavaScript, a String is a "subclass" of Object. Lucky for you, there's the typeof operator;
in the Chrome console
var a = "foo" //makes a String
var b = {} //makes an empty Object
typeof a
"string"
typeof b
"object"
Using this, you can check to ensure something is not a string before doing an operation on it.
Other option: instead of iterating using the json $.each call, you could just iterate over it via a JavaScript for-loop. If you know the number of elements inside your SomeNameIGaveIt object is fixed, you could use a fixed number of iterations and then use the array indexing operator (SomeNameIGaveIt[index]), or use a for-in loop (for (var i in array){...})
If you use a for-in loop, you can check if the index is a number using typeof as mentioned above. Any of these approaches is going to yield pretty similar results, so pick whatever suits you best.

Related

Properly detecting numeric data in ajax xml response

I'm using jQuery to post ajax requests, and PHP to construct XML responses. Everything works fine, but I wonder about the method I've used for data typing, and whether there's a more standard way, or a more correct way. My XML generally looks like this, with some attributes representing text and other attributes representing numeric data:
<UnitConversions>
<UnitConversion basicUnitName="mile" conversionFactor="5280" conversionUnit="foot"/>
<UnitConversion basicUnitName="mile" conversionFactor="1760" conversionUnit="yard"/>
</UnitConversions>
I have a lot of different objects, not just this one type, so in my constructors, rather than initializing every property explicitly, I just copy the attributes over from the XML node:
var UnitConverter = function(inUnitConversionNode) {
var that = this;
$.each(inUnitConversionNode.attributes, function(i, attribute) {
that[attribute.name] = attribute.value;
});
};
I had trouble early on when I checked for numeric values, as in if(someValueFromTheXML === 1) -- this would always evaluate to false because the value from the XML was a string, "1". So I added nodes in key places in the XML to tell my client-side code what to interpret as numeric and what to leave as text:
<UnitConversions>
<NumericFields>
<NumericField fieldName="conversionFactor"/>
</NumericFields>
<UnitConversion basicUnitName="mile" conversionFactor="5280" conversionUnit="foot"/>
<UnitConversion basicUnitName="mile" conversionFactor="1760" conversionUnit="yard"/>
</UnitConversions>
So now I pass the NumericFields node into the constructor so it will know which fields to store as actual numbers.
This all works great, but it seems like a bit of a naive solution, maybe even a hack. Seems like there would be something more sophisticated out there. It seems like this issue is related to XML schemas, but my googling seems to suggest that schemas are more about validation, rather than typing, and they seem to be geared toward server-side processing anyway.
What's the standard/correct way for js to know which fields in the XML are numeric?
You can use isNaN() to detect whether the string is a number. For example isNaN("5043") returns false indicating that "5043" can be parsed as a number. Then, just use parseInt() to compare the value. For example:
if (parseInt(someValueFromTheXML, 10) === 1) {
...
}
Another way is to use loose comparison with the == operator so that "1" == 1 evaluates to true. However, it would be better practice to use the first suggestion instead. There is really no other way to go about this since XML/HTML attributes are always strings.

Accessing JSON Object property

These are my JSON objects.
({
"0":"http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F86040788&amp",
"1":"http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F87126537&amp",
"2":"http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F84915833&amp",
"3":"http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F87317484&amp",
"4":"http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F86548283&amp"
})
I fetched them with Ajax and this is how I get to them:
data[0] to data[4].
Why is data.1, etc not working? I don't understand why I can access the objects like this data[0], because they are not arrays.
Why is data.1, etc is not working?
Thats because data.1 is an invalid syntax according to the grammar of Javascript. Open your browsers console and try:
var obj = {};
obj[0] = "test";
obj.0; //SyntaxError: Unexpected number
I don't get why I can acess the objects like this data[0], because they are not arrays.
In javascript, arrays and map/dictionary/association array are the same thing. You can access by either object[key] syntax or object.key syntax. Only restriction is that it should be parseable by the parser (it should be an identifier), otherwise it would fail -- like the case you have. Another example:
var obj = {"test-data":1, "test": 2};
obj["test"] // 2
obj.test // 2
obj["test-data"]; // 1
obj.test-data //ReferenceError: data is not defined
//^ is a <MINUS> character, parsed as (obj.test - data)
Working with objects: Objects and properties
An object property name can be any valid JavaScript string, or
anything that can be converted to a string, including the empty
string. However, any property name that is not a valid JavaScript
identifier (for example, a property name that has space or dash, or
starts with a number) can only be accessed using the square bracket
notation. This notation is also very useful when property names are to
be dynamically determined (when the property name is not determined
until runtime). Examples are as follows:
because json var name could not start from digit

Finding the length of an associative array encoded by PHP

I have a multidiminsional array that I have created in php that is passed back to a jQuery script. I need to iterate through this array and process the data.
In Firebug I can see that the data is located at data.data.items. I've tried finding the length of the array using data.data.items.length, but it comes back as undefined. Interestingly, this worked prior to my php portion working correctly when it passed back an array of 8 empty items. Now that it's populated (and the indexes are strings), length doesn't work. There is also an object in each of the items. What's breaking this?
An Array in JavaScript is an object nonetheless. When setting values using strings (or anything that isn't an integer), you are actually setting a property of the object (you are actually doing this when setting it with integer keys as well, but it's handled slightly differently).
To the issue of its sudden breakage after using strings as keys, I would expect that PHP realizes when you have an honest-to-goodness array versus an associative array, thus it sends arrays (surrounded by []) when all keys are integers, and objects (surrounded by {}) otherwise. I believe in the string-keyed case, PHP is generating objects, and thus .length becomes undefined (rather than 0 as in an empty array).
To answer your question, there is a simple way to count the "length" of this data:
var i = 0;
for (var item in data.data.items) {
i++;
}
Which will iterate through each property of data.data.items and count them. Note that if you (or any library you include) adds a property to the Object prototype, this will not produce expected results. This is fairly uncommon, but you must be aware of it when using for..in.
You can address this by using the method Nagh suggested, which ignores properties not defined on that particular object:
var i = 0;
for (var item in data.data.items) {
if(data.data.items.hasOwnProperty(item)) {
i++;
}
}
You can always use "foreach" kind of loop. In this case, you don't need to know what array length is there or even is it array or not, since you can iterate over object properties aswell.
As Joe already has pointed, javascript doesn't have associative arrays and when you trying to use one - you end up with object with properties. However, if u sure, that only properties this object got - is your array you can use code like that:
for (i in arr) {
if (arr.hasOwnProperty(i)) {
//do something with arr[i]
}
}
However if you really need an array, consider using integer as an array index.

decoding json from mysql result

I encoded a mysql result from php to json.. I need to decode it in javascript. Say my string returned is
[{"0":"x","1":"z"},{"0":"xs","1":"zz"}]
Please help me on how to get the value of a particular row and column.. for instance how to get the value of "0" of the second row.
EDIT:
Sorry for bothering friends my mistake.. the typeof returned as string JSON.parse(data) did the trick..
var data = [{"0":"x","1":"z"},{"0":"xs","1":"zz"}];
alert (data[1]["0"]);
gives you the xs
The [] represents an array structure, with each {} being an element in the array. Then, within each object there is a set of attributes, which you get it via the attribute's identifier. In this case, it's 0, so it could have just be 0 as well.
Why make objects? It is very poor coding standard to NAME attributes with a number.
Since it obviously are arrays do this instead
var x = [["x","z"],["xs","zz"]]
Then
x[1][0] will give you xs

jQuery json_encode

I've looked around for a Javascript/jQuery function which emulates PHP's json_encode, but all the ones I find (listed bellow) don't work.
http://code.google.com/p/jquery-json/
http://phpjs.org/functions/json_encode:457
To check if it wasn't my array wasn't faulty I used phpjs var_dump with expected results.
Can anyone point me in the right direction?
The problem is that you cannot do this:
ret[$(this).attr("id")] = _recursiveItems(this);
because var ret = [] declares ret as an Array and not an Object and $(this).attr("id") is non-numeric (its value is head_1). It is attempting to create an associative array which is not supported.. JavaScript associative arrays are are meant to be numeric and even considered harmful.
If you change the declaration to var ret = {} then you can use jquery-json to convert the object to JSON. Here is a demo using the code in the question.

Categories