JSON key is called "true", unable to reference in JavaScript(JSfiddle example) - javascript

First of all, I converted a Plist(XML formatted) to JSON with some online tool, this isn't the problem. I managed to pick the important values from this rather big JSON file. With this important information I am rebuilding a new JSON file that is very lean and contains information I can use for a plug-in — that I will create later.
The plist conversion to JSON is ugly. At some point <true/> and <false/> are converted to JSON, leaving this in the JSON: "false":"", or "true":"",.
I am using jQuery
check JSfiddle for an example jsfiddle example
or here
// Simplified (not really a JSON file, but this will do it for explaining)
var themeJSON = {
"item": {
"false": "",
},
};
// I need to know if its enabled: "true" or disabled: "false"
// function for checking if this is the default option
function checkDefault() {
// true is a keyword!
if (themeJSON.item.true) {
return "1";
// so is false!
} else(themeJSON.item.false) {
return "0";
}
}
Maybe I use some other function such as find() ?
updated for answer:
thanks to the comments, this is what I have now:
function checkDefault() {
if (item.hasOwnProperty("true")) {
return "1";
} else if(item.hasOwnProperty("false")) {
return "0";
}
}

Try using the property name as a string:
if (themeJSON.item['true']) {
return '1';
}
else if (themeJSON.item['false']) {
return "0";
}
edit — a comment correctly points out that though accessing the properties by string value will indeed work, your code is otherwise flawed. If the properties are really being given empty string values, then what you really need is a way to test whether the property is there at all, and not (as this code does) just check the value of the property:
if (typeof themeJSON.item['true'] !== 'undefined') { ... }
or, alternatively:
if ('true' in themeJSON.item) { ... }
An explicit check for equality against the empty string would do too:
if (themeJSON.item['true'] === '') { ... }

When an object property has a name which is a reserved keyword, the array index notation can be used to reference it.
A way of checking whether item has a property named false:
> themeJSON.item.hasOwnProperty("false");
true
This not ideal because a single object could have both a false property and a true property.

In JS, foo.bar is the equivalent of foo['bar']. Therefose:
if (themeJSON.item['true'] === "")
Note the need for === as false == "" but false !== "".
Also, I must nitpick. themeJSON is no longer JSON since it's not a string - it's just another JavaScript object. You shouldn't confuse those two.

Try this code
function checkDefault() {
// true is a keyword!
if ("true" in themeJSON.item) {
return "1";
// so is false!
} else if ("false" in themeJSON.item) {
return "0";
}
}

Related

How to replace a dynamically specified attribute in JS object

The attribute(or the nested object) is selected dynamically based on conditions. It can be one of the 4 possibilities as follows:
var tempData = o.title ? o["properties"] || o["items"]["properties"] : o[k]["properties"] || o[k]["items"]["properties"];
Then I get this new data, I want to replace the above selected with.
var newData = //some new Object
I want to replace whatever above selected with the new data. I could do the following (go through the condition again and set the new data):
if(o.title){
if (o["properties"]) {
o["properties"] = newData;
} else if (o["items"]["properties"]) {
o["items"]["properties"] = newData;
}
}else{
if (o[k]["properties"]) {
o[k]["properties"] = newData;
} else if (o[k]["items"]["properties"]) {
o[k]["items"]["properties"] = newData;
}
}
But it doesn't look good. What is the more sophisticated way of achieving this?
It is unclear if you are generically attempting to replace any properties property with the newData, or if you are wanting it to specifically be one of the ones you have specified in your code. I have assumed that you are only wanting to replace the ones you specifically have shown in your code.
Note: The following assumes that it is not possible for the value of the properties property to evaluate to false. If it is possible for it to have a value that evaluates to false, this will fail.
As a first pass, I would do something like:
var p;
if (o.title) {
p=o;
} else {
p=o[k];
}
if (p.properties) {
p.properties = newData;
} else if (p.items.properties) {
p.items.properties = newData;
}
However, that relies on:
o is not null or undefined.
o.title does not evaluate to false, if you are trying to test for the existence of o.title.
k is valid/defined.
p (i.e. o[k]) is not null or undefined (i.e. is an Object)
p.properties does not evaluate to false, if you are testing for existence
p.items is not null or undefined (i.e. is an Object)
p.items.properties does not evaluate to false, if you are testing for existence
A more robust implementation would be:
if (typeof o === 'object' && o !== null) {
var p;
if (o.hasOwnProperty('title')) {
p = o;
} else {
p = o[k];
}
if (typeof p === 'object' && p !== null) {
if (p.hasOwnProperty('properties')) {
p.properties = newData;
} else if (typeof p.items === 'object' && p.items !== null
&& p.items.hasOwnProperty('properties')) {
p.items.properties = newData;
}
}
}
This still relies on:
k is valid/defined.
Basically, it is OK to use shortcuts like if(o.title) to test for existence, if you know that
the possible values for o can not include ones which might make your code throw an error (e.g o is null or undefined), and
the possible values for o.title do not evaluate to false when the property actually exists (e.g. o.title is null, undefined (yes, the property can exist, but have the value undefined), false, 0, '', etc.).
If you are going to perform the replacements in other areas of your code, or if you are going to use property keys other than hard coded items, and properties, then you should create a function. Assuming you are only performing this replacement in this section of your code, using a variable to hold the object in which you are looking for properties is faster/more efficient than creating a function.
Ok, from what i can understand here, it's like you are trying to replace the "properties" with the new data, and you want this to be able to be done dynamically, or maybe i can say, you need to do this regardless the structure.
lets see, if your objective is anything that end up with "properties", lets do it like this:
function recReplace(current,target,replacement){
for (var i in current){
if (i == target){
current[i] = replacement;
}
else{
recReplace(current[i],target,replacement);
}
}
}
And in the end you call
recReplace(o,"properties",newData);
But this will replace whole "properties" key with newData in DFS way, you can do additional conditional if you want to replace it only the first occurence

To check the JavaScript object has a value

Can you tell me how to check the JavaScript object has a value ? This vm.occupantDetail.contactDetail object is neither null nor undefined.It looks like as shown below at run time.
It defines as shown below.
vm.occupantDetail = {
contactDetail: {},
};
You can find the it using
Object.keys(vm.occupantDetail.contactDetail).length
It appears from your code that your vm.occupantDetail.contactDetail object is simply an empty object, and the __proto__ property that you are seeing is the protoype property of the Object. If you want to check if an object is null, the following conditional will do the job.
if (obj == null) { ... }
However, it appears that you want to check if an object is empty, which is different. If you want to check if a specified object has no assigned properties, try the following function.
function isEmpty(map) {
for(var key in map) {
if (map.hasOwnProperty(key)) {
return false;
}
}
return true;
}
check it by jQuery.isEmptyObject()
jQuery.isEmptyObject({}); // true
jQuery.isEmptyObject({ foo: "bar" });
https://api.jquery.com/jQuery.isEmptyObject/
Check the length of your object also the length of your keys.
if (Object.keys(vm.occupantDetail.contactDetail).length > 0)
{
// vm.occupantDetail.contactDetail has values
}

How to properly access nested JavaScript objects?

I have ruby background and am converting some ruby code to JavaScript.
I'm trying to understand the difference between hashes in ruby and JavaScript.
I have a hash in ruby that looks like below:
main_hash = {"query" => { "filtered" => { "query"=> { "bool" => query_hash}}}}
I think the proper conversion for this in JavaScript would be basically a JSON like below:
var main_hash = {"query" : { "filtered" : { "query" : { "bool" : query_hash}}}}
But, I have some ruby logic that I'd like to replicate in JavaScript. And that code is:
if(query_hash.empty?)
main_hash["query"]["filtered"].delete("query")
else
main_hash["query"]["filtered"]["query"]["bool"] = query_hash
end
How do I access the nested attributes in JavaScript?
The reading I've been doing on w3schools indicates the below is the correct conversion, but I want to make sure I'm not missing any language semantics in this conversion. For example the delete only deletes the query object contained in filtered which is contained in query that is contained in main_hash correct?
if(!isEmptyObject(query_hash)){
delete main_hash.query.filtered.query;
} else {
main_hash.query.filtered.query.bool = query_hash;
}
In JavaScript, your Ruby hash equivalent is an object. Properties of objects can be accessed two ways.
You can access them with the dot notation:
main_hash.query.filtered.query
Or using the array like access:
main_hash["query"]["filtered"]["query"]
Both work. And yes, the delete would only delete the innermost query property.
If you are using JQuery your code is ok, but if you are not, you need to create this isEmptyObject function.
You can use something like this function
function isEmpty(obj) {
// Speed up calls to hasOwnProperty
var hasOwnProperty = Object.prototype.hasOwnProperty;
// null and undefined are "empty"
if (obj == null) return true;
// Assume if it has a length property with a non-zero value
// that that property is correct.
if (obj.length > 0) return false;
if (obj.length === 0) return true;
// Otherwise, does it have any properties of its own?
// Note that this doesn't handle
// toString and valueOf enumeration bugs in IE < 9
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) return false;
}
return true;
}
Examples:
isEmpty(""), // true
isEmpty([]), // true
isEmpty({}), // true
isEmpty({length: 0, custom_property: []}), // true
isEmpty("Hello"), // false
isEmpty([1,2,3]), // false
isEmpty({test: 1}), // false
isEmpty({length: 3, custom_property: [1,2,3]}) // false

form.serializeArray() converts each element into string

Trying to form.serializeArray() and passing serialized data to the server.
Problem: This method also converts boolean and integer to string. And on server side on the basis of the
value , I am trying to get the data type because of which it gives me String everytime.
Actual Output:
[Object { name="para1", value="1"}, Object { name="para2", value="2"}, Object { name="para3", value="true"}, Object { name="para4", value="rep1"}]
Required Output:
[Object { name="para1", value=1}, Object { name="para2", value=2}, Object { name="para3", value=true}, Object { name="para4", value="rep1"}]
Please suggest the solution for this.
You could process the value string of each object and create a new array with converted values. For example, the strings true and false would be converted to their respective boolean value and numbers would be converted to integers. Note that my example below is quite simple and doesn't cover all possibilities (floats are also converted to integers).
Edit: As noted by #sanfor in the comments, every string containing an integer is converted to an integer value, although strings like "123" could also be treated as strings. However, given the information in the question that the type of the input is unknown, this method provides the desired results.
JSFiddle (open the console to see the output):
var values = [
{
name: 'para1',
value: '1'
},
{
name: 'para2',
value: 'true'
},
{
name: 'para3',
value: 'this is a string'
}
];
var result = values.map(function(obj) {
var value;
if (obj.value === 'true') {
value = true;
} else if (obj.value === 'false') {
value = false;
} else if (!isNaN(obj.value)) {
value = parseInt(obj.value);
} else {
value = obj.value;
}
return {
name: obj.name,
value: value
};
});
console.log(result);
As #Vohuman already mentioned, the values are strings as intended. To make them something else you would need to either use some other function to achieve it, or handle the output of the serializeArray afterwards.
More likely solution is to teach your back-end to resolve the type based on the field. You usually know what you are expecting on back-end so you also know the type required and based on that you can (try) to cast it to be correct type.

Finding a property in a JSON Object

I'm creating a JSON object like
tags = {"jon":["beef","pork"],"jane":["chicken","lamb"]};
which was generated using php from an array like
$arr = array(
'jon' => array('beef', 'pork'),
'jane' => array('chicken', 'lamb')
);
$tags = json_encode($arr);
And I want to check if something is in one or the other. None of these seem to work, but something like
if('lamb' in tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
writes NO to the console
if('foo' in tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
also writes NO to the console
so looking at
typeof(tags.jane);
it shows it's an "object" but
console.log(tags);
shows the following:
Object
jane: Array[2]
0: "chicken"
1: "lamb"
length: 2
__proto__: Array[0]
jon: Array[2]
0: "beef"
1: "pork"
length: 2
__proto__: Array[0]
__proto__: Object
so i thought maybe tags.jane may actually be an array and tried
if($.inArray('lamb', tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
which writes YES to the console but
if($.inArray('foo', tags.jane)) {
console.log('YES');
} else {
console.log('NO');
}
also writes YES to the console.
Am I incorrectly building the JSON Object? Not targeting the value(s) properly? Any advice is greatly appreciated. If this would be easier as an array instead of an object, I have full control to change it. I'm just a bit stumped at how I should treat this.
jQuery.inArray returns -1 when element is not found. That's true value from the POV of Javascript. Try this:
if($.inArray('foo', tags.jane) != -1) {
Your second set of answers are the way you should go. However, $.inArray returns an index, not a boolean. Any non-zero integer is true, which means when foo is not found, it returns -1 which evaluates to true and prints YES.
Similarly, $.inArray('chicken', tags.jane) would return 0 and cast to false, which is also not the answer you want.
Instead, use $.inArray('foo', tags.jane) !== -1 as your condition.
tags.name will give you the array for that person. So $.inArray("chicken",tags.jane) would see if "chicken" is in jane's tags array. If it's not, you'd get -1, otherwise you'd it's position in the array (using your example, this would return zero, the first array element).
You're using the keyword in for the wrong reason.
The statement ( prop 'in' obj ) checks to see if the object(associated array) has a property with the value of prop.
Since you're using the 'in' keyword on an array, then false is going to be returned because tags.jane is an array with indexes and not an associated array with properties.
If you want to know was values are in the array then loop through and compare.
If you want to use the 'in' keyword then convert your array to an object like so.
tags = {};
// old code
tags.jane = ['lamb', 'food'];
console.log(('lamb' in tags.jane) === false )
// new code
tags.jane = {
'lamb':1,
'food':1
}
console.log(('lamb' in tags.jane) === true )
https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
you can not use
if('foo' in tags.jane))
it should be used as
if (1 in tags.jane)
if you want to check 'foo' is in tags.jane, try this
var inIt = (function() {
var inIt = false;
tags.jane.forEach(function(item) {
inIt = inIt || 'foo' == item;
});
return inIt;
})();

Categories