Getting JSON object values by name - javascript

I have a valid JSON object like this:
{
"reasons": {
"options": [
{
"value": "",
"label": "Choose a reason",
"selected": true,
"requiresValidation": false
},
{
"value": "small",
"label": "Too little",
"selected": false,
"requiresValidation": false
},
{
"value": "big",
"label": "Too big",
"selected": false,
"requiresValidation": false
},
{
"value": "unsuitable",
"label": "I don't like it",
"selected": false,
"requiresValidation": true
},
{
"value": "other",
"label": "Other",
"selected": false,
"requiresValidation": true
}
]
}
}
and I have a variable which stores one value (e.g. unsuitable) of an option available in options.
How can I retrieve the value of requiresValidation field for the value stored in the variable without having to loop through all of the objects values inside options?
For instance, if the var content is other I'd like to access to requireValidation field of the object whose value is other (which is true). Is it possible?
Thank you.

You aren't really dealing with JSON here, you are dealing with a JS object. JSON is just a format for sending JS objects.
options is an array. The only way to access it is by index, which means you will have to do a search, one item at a time. There are functions, such as indexOf() which will return the first index of a value in an array, however, you have an array of objects, so that will not work in this case. (And internally, it is still doing a search).
function getReqVal(val) {
for (var item in mydata.reasons.options) {
if(item.value == val) {
return item.requiresValidation;
}
}
}
getReqVal("other");
The caveat is that this will return on the first one, so if you have more than one other, you won't get them.
If the options are indeed unique values, I would rearrange your object to be an associative array, with the keys being the "value" items, and the values being an object with the rest of the data:
{
"reasons": {
"options": {
"" : {
"label": "Seleziona una voce",
"selected": true,
"requiresValidation": false
},
"small" : {
"label": "Too little",
"selected": false,
"requiresValidation": false
},
"big" : {
"label": "Too big",
"selected": false,
"requiresValidation": false
},
"unsuitable" : {
"label": "I don't like it",
"selected": false,
"requiresValidation": true
},
"other" : {
"label": "Other",
"selected": false,
"requiresValidation": true
}
}
}
}

If you are (or could be) using underscore.js you could use the find method:
var item = _.find(myObj.reasons.options,
function(option){ return option.value == 'some value' });

Assuming you can't change the JSON structure itself (because perhaps you're getting it from an external source?), you can read it into a new object of your design per Marc B's suggestion. Ideally, this new object would let you index into your options array using the value key. Let's do that:
function MyOptions(optionsJSON) {
this.original_json = optionsJSON;
this.length = optionsJSON.reasons.options.length;
var original_options = optionsJSON.reasons.options;
for(var i = 0; i < this.length; i++)
this[original_options[i].value] = original_options[i];
}
var my_opts = new MyOptions(original_JSON);
var item_requiresValidation = my_opts["unsuitable"].requiresValidation;
console.log(item_requiresValidation); // should log "true"
The trade-off here is that your code will need to loop through the entire options array once, but after that you can index into the objects using the value key without searching. Validate with this jsfiddle.

You could use array filter. Some variation of this:
var $reasons = //Your JSON
function checkVal(element, index, array) {
return (element.value == "other");
}
var filtered = $reasons.reasons.options.filter(checkVal);
alert(filtered[0].requiresValidation);
Or jQuery grep might help you with the filter without looping: http://api.jquery.com/jQuery.grep/

Related

How to access the right json value that is located through an array?

I'm currently using the fixture file to make sure it will be easier to call the right value.
cy.fixture('latestLead.json').then(function (lead) {
this.lead = lead
})
My son file is the following:
{
"status": 0,
"result": {
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "Lead",
"url": "/services/data/v51.0/sobjects/Lead/111111111"
},
"Id": "111111111",
"Name": "Andres Latest Test"
}
]
}
}
The way that I'm trying to get the right value is the following:
cy.get(".gLFyf").type(this.lead.result.records.Id)
I'm able to get totalSize or done from the result object, but I'm not able to get any other value higher than that object. How can I get the Id value from the records Array?
You can access an array item (in your case it's the object) using the index position (in your case it's zero)
cy.get(".gLFyf").type(this.lead.result.records[0].Id)
try this
cy.get(".gLFyf").type(this.lead.result.records[0].Id)

How to check if multiple objects in array have the same property value?

Hey guys I want to know what is the best approach to check wether two or more objects has the same property value in my case dueTo?
My array looks like this
Array [
Object
"__typename": "Instalment",
"_id": "5cd022cf0d805222374197eb",
"description": "Description",
"dueTo": "2019-05-16T23:00:00.000Z",
"instalmentAmount": 200000,
"paid": false,
},
Object {
"__typename": "Instalment",
"_id": "5cd022cf0d805222374197ea",
"description": "Description",
"dueTo": "2019-05-23T23:00:00.000Z",
"instalmentAmount": 200000,
"paid": false,
},
Object {
"__typename": "Instalment",
"_id": "5cd022cf0d805222374197e9",
"description": "Description",
"dueTo": "2019-05-23T23:00:00.000Z",
"instalmentAmount": 200000,
"paid": false,
},
]
First I want to know which objects include the value paid: false
const unpaidInstalments = instalments.filter(
instalment => !instalment.paid
);
Now I want to check if there are instalments in the same day in this case will result to index 1 and 2 and here the question come how do I filter this?
SOLVED
Get all the available dates and put them in an object then check if there is more than 1 object which contain the same value and return an array with these objects
const sameDayArray = unpaidInstalments.reduce(
(datesToCheck, instalment) => {
datesToCheck[instalment.dueTo] =
(datesToCheck[instalment.dueTo] || 0) + 1;
return datesToCheck;
},
{}
);
const instalmentsSameDay = unpaidInstalments.filter(instalment => {
return sameDayArray[instalment.dueTo] > 1;
});

Matching certain value in JSON Array using match() or find() in JavaScript

I'm looking for a function or method to overcome this issue
Here is the JSON Array
[{
"type": "radar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}, {
"type": "bar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}]
I'm hoping to identify the value of "type" which in this case would be "radar" and "bar",and match with the variable x。
Here's the code:
for(x in myarray)
{
if(myarray[x]['type']=="bar")
{
console.log("equal");
}
else
{
console.log("no result");
}
}
With this code,the result on the website console would be both "equal" and "no result",while I wish to print "equal" only.I understand the logic error in this code,but I couldn't figure out the correct way to fix it.
You can use Array.some for this which return true or false if one of the array element match with type "bar" then It will return true otherwise false
var data = [{
"type": "radar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}, {
"type": "bar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}]
if (data.some(val => val.type == "bar"))
console.log("Equal")
else
console.log("No record found");
let myArr = [
{ "type":"radar",
"detail": [
{ "subject":"sub1" },
{ "subject":"sub2" }
]
},
{ "type":"bar",
"detail": [
{ "subject":"sub1" },
{ "subject":"sub2" }
]
}
]
for(let x of myArr){
if(x.type === 'bar'){ console.log('equal')}
else { console.log('no result')}
}
In order to understand what went wrong with your code, first when you have a for loop, you need to have a let/var keyword as below:
for(let x of myArr)
Secondly, instead of using for..in loop, which it meant for looping property of objects, use for..of loop which meant for looping array.
Third, while looping myArr, each and every element x is an object and type is the property, so just use x.type to make the comparison.
Lastly, as others have mentioned, Array#some / Array#find is a better way to deal with finding existence of element in an array
Since the for loop runs for each object in the array, the first console log for equal is for matched type and second console log is for the unmatched type. So, to get only one console and to write more appropriate code, you can use Array.find() and then add a if-else block for that. Something like this:
var myarray = [ { "type":"radar", "detail": [{ "subject":"sub1" }, { "subject":"sub2" }] }, { "type":"bar", "detail": [{ "subject":"sub1" }, { "subject":"sub2" }] } ];
var match = myarray.find(({type}) => type === "bar");
if(match) {
console.log("equal");
} else {
console.log("no result");
}

Check array of objects in lodash for property value

Given the following
var content = [{
"set_archived": false,
"something": [{
"id": "aa7bb3db-19a2-4ef6-5944-892edaaf53c3",
"modified": "2016-12-01T18:23:29.743333Z",
"created": "2016-12-01T18:23:29.743333Z",
"archived": false
}]
},
{
"set_archived": true,
"something": [{
"id": "aa7bb3db-19a2-4ef6-5944-892edaaf53c3",
"modified": "2017-01-30T19:42:29.743333Z",
"created": "2017-01-30T19:42:29.743333Z",
"archived": false
}]
}
];
Using Lodash, how would I determine if either set_archived or something.archived in the array of objects is equal to true?
So in this case, because the second object has set_is_archived that is true, then the expected response should be true. If all items are false in either object, then the response should be false.
Just use:
_.filter(content, o => o["set_archived"] || o.something[0].archived).length > 0;
or
_.some(content, o => o["set_archived"] || o.something[0].archived);
PlainJs:
content.some(o => o["set_archived"] || o.something[0].archived)
or
content.filter(o => o["set_archived"] || o.something[0].archived).length > 0;
You can just use some() in plain javascript.
var content = [{
"set_archived": false,
"something": [{
"id": "aa7bb3db-19a2-4ef6-5944-892edaaf53c3",
"modified": "2016-12-01T18:23:29.743333Z",
"created": "2016-12-01T18:23:29.743333Z",
"archived": false
}]
}, {
"set_archived": true,
"something": [{
"id": "aa7bb3db-19a2-4ef6-5944-892edaaf53c3",
"modified": "2017-01-30T19:42:29.743333Z",
"created": "2017-01-30T19:42:29.743333Z",
"archived": false
}]
}];
var result = content.some(function(e) {
return e.set_archived === true || e.something[0].archived === true
})
console.log(result)
Considering the same object as the one in the question, there are couple of ways to find the solution to your problem mate.
var flag = false;
flag = content.some(function(c){
if(c["set_archived"]){
return true;
}
});
console.log(flag)
or
var flag = false;
flag = content.some(function(c){
if(c["set_archived"] || c.something[0].archived){
return true;
}
});
console.log(flag)
The above snippet will result true if atleast one of the object of the array have ["set_archived"] property true and it will return false if all the objects of the array has ["set_archived"] as false. (I could have said vice-versa)
The some() method tests whether some element in the array passes the test implemented by the provided function.
The every() method tests whether all elements in the array pass the test implemented by the provided function.
If you are looking for a stricter way I recon you go ahead with every().
You don't need lodash for this. You can do this with pure JS, using filter:
content.filter(i => i.set_archived || i.something.archied)

Merge and array from within an object to every key form object

So, I have an object as follows:
custom_fields:{
21:{
edit:true
required:true
show:true
}
}
Which in my angular controller is stored here: $scope.page.custom_fields
Within this object I have another one, like this:
custom_fields:{
21:{
edit:true
required:true
show:true
}
22:{
edit:true
required:true
show:true
}
data:[
0:{
display_name:"Text"
id:21
name:"Text"
value:[
0:{"TextHere"}
]
}
1:{
display_name:"Text"
id:22
name:"Text"
value:[
0:{"TextHere"}
]
}
]
}
This one is stored like this: $scope.page.custom_fields.data = response.data.custom_fields;
As you can see the first one is an object of objects while the second one is an array of objects. I don't know why they ended up like this, but I would need to assign the first key in data to the first key in custom fields, so they would look like this in the end:
custom_fields:{
21:{
edit:true
required:true
show:true
display_name:"Text2"
id:21
name:"Text"
value:[
0:{"TextHere"}
]
}
}
I should do this in the angular controller. As you can see every id from data corresponds to the key in custom_fields (in this case 21:{} and data[0:{id:21}])
But they are being put in order by a foreach in php so there is no need to make a foreach in js too, I only have to assign in order every key from custom_fields.data to every key from custom_fields
But how can I do this?
data[0:{id:21}]
No, this is not possible.
Please refer link
numeric-type-as-an-object-key
It will be very difficult to use the $scope.page.custom_fields.21 later in your code. So better use it as array format instead of object. Following code will help you parse it in array of objects of custom fields.
angular.forEach($scope.custom_fields.data, function(value, idx){ // may be $scope.custom_fields.custom_fields.data as per your code. Please correct accordingly.
if($scope.custom_fields[value.id]){
angular.merge($scope.custom_fields.data[idx], $scope.custom_fields[value.id]);
delete($scope.custom_fields[value.id]);
}
});
$scope.custom_fields = $scope.custom_fields.data;
console.log($scope.custom_fields);
let custom_fields = {
"21": {
"edit": true,
"required": true,
"show": true
},
"22": {
"edit": true,
"required": true,
"show": true
},
"data": [{
"display_name": "Text",
"id": 21,
"name": "Text",
"value": ["TextHere"]
}, {
"display_name": "Text",
"id": 22,
"name": "Text",
"value": ["TextHere"]
}]
};
custom_fields.data.forEach(function(item) {
let obj = custom_fields[item.id];
for (let attr in item)
obj[attr] = item[attr];
});
//Remove the data property
delete custom_fields.data;
console.log(custom_fields);
As I said in comment, I think you need a loop to asign each custom fields
var i = 0;
for (var key in custom_fields) {
if (custom_fields.hasOwnProperty(key)) {
// only if you are sure that data is ordered, else must be filter data by custom_fields[key].id
custom_fields[key].display_name = data[i].display_name;
custom_fields[key].name = data[i].name;
custom_fields[key].value = data[i].value;
i++;
}
}
I hope this will help you

Categories