parsing a json in loop where element names change - javascript

I'm parsing a JSON response which isn't set up the best, in my opinion. Here is the actual response:
[
{"challenge_id":"39029"},
{"song1_id":"198","name":"PRAY","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/TAKE_THAT_-_PRAY.mp3"},
{"song2_id":"251","name":"THE TEARS OF A CLOWN","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/SMOKEY_ROBINSON_-_THE_TEARS_OF_A_CLOWN.mp3"},
{"song3_id":"11","name":"WONDERFUL TONIGHT","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/ERIC_CLAPTON_-_WONDERFUL_TONIGHT.mp3"},
{"song4_id":"288","name":"THE NAME OF THE GAME","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/ABBA_-_THE_NAME_OF_THE_GAME.mp3"},
{"song5_id":"159","name":"I'M EVERY WOMAN","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/CHAKA_KHAN_-_I'M_EVERY_WOMAN.mp3"},
{"status":"ok"}
]
and here was my attempt at parsing it:
var challenge_Songs = JSON.parse(this.responseText);
for(var i = 1; i<challenge_Songs.length-1; i++){
challengeSongs[i-1] = challenge_Songs[i].url;
challengeTitles[i-1] = challenge_Songs[i].name;
voteSongIds[i-1]= challenge_Songs.song[i]_id;
}
My problem is with obtaining what I have set up as voteSongIds, as the name changes within every iteration of the loop. What I have tried above is causing a run time error. If I comment the line with votesongids, everything works. How should I parse the parse JSON?! Any help appreciated :) I'm using titanium, but for these purposes, it's just javascript!

Is this the result you looking for?
var challenge_Songs = [
{"challenge_id":"39029"},
{"song1_id":"198","name":"PRAY","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/TAKE_THAT_-_PRAY.mp3"},
{"song2_id":"251","name":"THE TEARS OF A CLOWN","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/SMOKEY_ROBINSON_-_THE_TEARS_OF_A_CLOWN.mp3"},{"song3_id":"11","name":"WONDERFUL TONIGHT","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/ERIC_CLAPTON_-_WONDERFUL_TONIGHT.mp3"},
{"song4_id":"288","name":"THE NAME OF THE GAME","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/ABBA_-_THE_NAME_OF_THE_GAME.mp3"},
{"song5_id":"159","name":"I'M EVERY WOMAN","url":"https:\/\/s3-eu-west-1.amazonaws.com\/test\/CHAKA_KHAN_-_I'M_EVERY_WOMAN.mp3"},{"status":"ok"}]
var challengeTitles=[],
challengeSongs = [],
voteSongIds=[];
for(var i = 1; i < challenge_Songs.length-1; i++){
challengeTitles.push(challenge_Songs[i]['name']);
challengeSongs.push(challenge_Songs[i]['url']);
voteSongIds.push(challenge_Songs[i]['song'+ i +'_id'])
}
console.log(challengeTitles);
console.log(challengeSongs);
console.log(voteSongIds);

Try the following code. This will work perfect whatever the key or value
for(var i = 0; i<challenge_Songs.length; i++){
for(key in challenge_Songs[i]){
console.log("\n key=>" + key + " : value=> " + challenge_Songs[i][key]);
}
console.log("\n");
}
It will display you all the keys and correspondent value in more simple way

Related

Search For Text in Div

I'm trying to make a runnable console command through Chrome that searches for the word "takeID", and then grabs the content immediately after it between = and & from a div class.
What I have so far doesn't work because I'm very bad at JS so any help would be appreciated. Below is what I have so far:
var iframe=document.getElementsByClassName("activity activity-container-html5");
var searchValue = "takeID";
for(var i=0;i<iframe.length;i++){ if(iframe[i].innerHTML.indexOf(searchValue)>-1){}};
var subString = iframe.substring( iframe.lastIndexOf("=")+1, iframe.lastIndexOf("&"));
console.log(searchValue+"="+subString);
An example of the div class it would be searching would look like:
<div class="activity activity-container-html5" config="{example text;takeID=cd251erwera34a&more example text}">
There are two issues with the code. The first issue is the searchValue posts to the console as whatever is in between the takeID, and not the actual result from searching. The second issue is that the code to search between = and & doesn't work at all and I don't know why. What is wrong with the code?
I just want an output that would post to the log or a popup window saying:
takeID=cd251erwera34a
EDIT:
Something else I thought of was how would you be able to just parse the div and then search for what is in between "takeID=" and "&"? I tried this but I was getting the error "Uncaught TypeError: iframe.lastIndexOf is not a function".
var iframe=document.getElementsByClassName("activity activity-container-html5");
var subString = iframe.substring( iframe.lastIndexOf("takeId=") + 1, iframe.lastIndexOf("&") );
console.log(subString);
I looked this up and I see this is because what it is trying to process is not a string but I'm not sure why that is or how to fix it.
I don't know about you but the best would be to use json directly inside the html tag like this:
<div class="activity activity-container-html5" config="{'example':'text', 'takeID':'cd251erwera34a', 'other':''}">
Or use an array and check manually if the one you are checking is the one you want, like this:
function config(element, searchValue) {
if (element.hasAttribute('config')) {
var configData = JSON.parse(element.getAttribute('config'));
var res = "";
for (var i = 0; i < configData.length; i++) {
if (configData[i].includes(searchValue)) {
res = configData[i];
break;
}
}
return res;
}
}
el = document.getElementsByClassName('activity activity-container-html5');
for (var i = 0; i < el.length; i++) {
console.log(config(el[i], "takeID"));
}
<div class="activity activity-container-html5" config='["example=text", "takeID=cd251erwera34a", "othertext=here"]'>
The array-type (second example) is most likely to work better than the simple json one (first one).
I figured out what I needed to do. Below is working code:
var iframe=document.getElementsByClassName("activity activity-container-html5");
var div = "";
for(var i=0;i < iframe.length; i++){
div += (iframe[i].outerHTML);
}
var take = /takeID=([a-z0-9]*)&/;
var capture = div.match(take);
var matchID = capture[1];
console.log(matchID);
window.alert("takeID=" + matchID);

Split json data using comma

I have a json which has a key "tag", which is returning data like this
"tags": "jname,gender,city"
but i want to append these value in separate span like below
<div class="info">
<span>jname</span><span>gender</span><span>city</span>
</div>
I am trying with this
$.getJSON("data.json", function(tagsposts) {
var items = [];
splitsVal = tag.split(",");
for (var i = 0; i < splitsVal.length; i++) {
obj.push({name:splitsVal[i]});
obj[i] = '<span>' + obj[i] + '</span>';
$('.tags-div').append(obj[i])
}
$.each(tagsposts, function(key, val) {
items.push('' + val['tags'] + '');
});
$('#tagsposts').append(items.join(""));
});
Am I doing correct
You're trying to split an undefined variable:
function(tagsposts) {
var items = [];
splitsVal = tag.split(","); // but tag doesn't exist...
(If you look at your browser console, which you should get into the habit of doing, you'll get a very clear message about why this isn't working: "ReferenceError: Can't find variable: tag".)
Since you haven't provided your JSON it's not possible to say exactly how to fix this. Assuming the full JSON is of the form
{"tag": "foo,bar,baz"}
then you would want
splitsVal = tagsposts.tag.split(",")
If there's more structure than that inside the JSON, you'll need to crawl down through that parsed object to find the "tag" value(s) you need.
There are lots of other problems here, however.
You also try to push onto an undefined array named obj; you'd need at least a var obj = [] outside that for loop. Though it's not clear why you're using obj at all, or trying to draw an object {name: val} into the DOM instead of just the value. What you're trying to do is just read splitsVal[i] so you can just do this:
for (var i = 0; i < splitsVal.length; i++) {
$('.tags-div').append('<span>'+splitsVal[i]+'</span>')
}
And you try to iterate over tagsposts as if it's an array when generating the #tagsposts contents. (Is your JSON an array? If so you need to iterate over it when getting the tag values too.)

jMeter - XPath Extractor does not let BSF Post Processor (with javascript code) to access multiple extracted matches

I have an XML response from server (SOAP) and I'm getting multiple values in it. XPath extracts all the values and stores them internally like Match_1, Match_2, Match_3, etc.
But I can't access them neither via BSF Post Processor nor via JavaScript code pasted in XML. It just refuses to return values then I address to them like this: ${Match_1}.
Example:
Response returns multiple contentGroupID values.
Debug Sampler reveals them:
contentGroupID=67
contentGroupID_1=67
contentGroupID_2=50
contentGroupID_3=38
contentGroupID_4=54
contentGroupID_5=46
We need to use each of these values in the next single request, so we add a code inside XML in place where we need those values to sit:
${__javaScript
(myOutput =''; var names = {};
for (var i = 1; i <= ${contentGroupID_matchNr}; i++)
{names[i] = "${contentGroupID_" + i + "}";}
for (var j = 1; j <= ${contentGroupID_matchNr}; j++)
{myOutput =
myOutput + '<ns8:forContentGroupId><ns2:id>' + names[j] + '</ns2:id></ns8:forContentGroupId>';},
myOutput)
}
Here we place the part of XML with values <ns8:forContentGroupId><ns2:id>' + ids + '</ns2:id></ns8:forContentGroupId> as many times as matches were found by XPath.
But the magic does not happen. The request is sent as follows:
<ns8:forContentGroupId><ns2:id>${contentGroupID_1}</ns2:id></ns8:forContentGroupId>
<ns8:forContentGroupId><ns2:id>${contentGroupID_2}</ns2:id></ns8:forContentGroupId>
<ns8:forContentGroupId><ns2:id>${contentGroupID_3}</ns2:id></ns8:forContentGroupId>
<ns8:forContentGroupId><ns2:id>${contentGroupID_4}</ns2:id></ns8:forContentGroupId>
<ns8:forContentGroupId><ns2:id>${contentGroupID_5}</ns2:id></ns8:forContentGroupId>
The same happens in case I set BSF Post Processor with JavaScript code and add a variable in XML.
The question is: how the hell can one access those magical values?
P.S. Everything works great then I use ForEach Controller. But the trick is I need to make single request with all the values, not multiple requests one after another.
Found the solution here:
BSF Post Processor witch JavaScript code:
var myOutput = '';
var names = {};
var str;
var value = 0;
var match = vars.get("contentGroupID_matchNr");
for (var i = 1; i <= match; i++)
{
var n = i.toString();
str = 'contentGroupID_' + n;
value = vars.get(str);
names[i] = value;
}
for (var j = 1; j <= match; j++) {
myOutput = myOutput +  '<ns8:forContentGroupId><ns2:id>' + names[j] + '</ns2:id></ns8:forContentGroupId>';
}
vars.put("array", myOutput);
Plus ${array} variable inside XML.
End of story! =)

How to remove a null element in jquery?

I have an application in which i am storing values in localstorage. By default my first value is null due to which i am getting error to run the code so i want to remove the first element and continue the processes. can anyone please help me how to remove first element from list?
Piece of my code is below:
var str = localStorage.getItem("appidlist");
var mySplitResult = str.split(",");
for(var i = 0; i < mySplitResult.length; i++) {
if (.....) {
.
.
}
}
where str returns null,1,2,3,.....
I hope my question is clear can anybody help me.
This should also work:
var str = localStorage.getItem("appidlist");
var mySplitResult = str.split(",");
mySplitResult.splice(0, 1);
You can use .shift().
mySplitResult.shift()
Instead of uing the shift() function, I would suggest you to create a function that return a new clean array. This will solve even the case where there are more than one (and in any postion) null value.
You can use this solution
This should do the trick:
var str = localStorage.getItem("appidlist");
var mySplitResult = str.split(",").splice(1); // Remove the first item.
for(var i = 0; i < mySplitResult.length; i++) {
// Stuff
}

Get value of JSON object with inner objects by HTML form field name without eval

I have a problem like this Convert an HTML form field to a JSON object with inner objects but in to the other direction.
This is the JSON Object response from the server:
{
company : "ACME, INC.",
contact : {
firstname : "Daffy",
lastname : "Duck"
}
}
And this is the HTML form:
<form id="myform">
Company: <input type="text" name="company" />
First Name: <input type="text" name="contact.firstname" />
Last Name: <input type="text" name="contact.lastname" />
</form>
And this is the (pseudo)code:
var aFormFields;
for (var i = 0, iMax = aFormFields.length; i < iMax; i++) {
var sFieldName = aFormFields[i].getAttribute('name');
eval("sFieldValue = oResponse."+sFieldName);
}
Ok my solution works, but i looking for a good way to remove the evil eval from the code.
And the solution should also work for form fields with any count of dots in the field name.
Instead of:
eval("sFieldValue = oResponse."+sFieldName);
Use for single dotted fields:
sFieldValue = oResponse[sFieldName];
This will retrieve the value via its key.
Now if you need more than that you need to do the following:
Split sFieldName on .
Loop over that array and go down in oResponse till you reach the value that you desire
Code could look like this:
var node = oResponse, parts = sFieldName.split('.');
while(parts.length > 0) {
node = node[parts.shift()];
}
// node will now have the desired value
Further information on "Member Operators":
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators
This works for a single property:
sFieldValue = oResponse[sFieldName]
But it won't work for nested data like contact.firstname.
For that, split the name by dots, and use loop through each name:
var aFormFields;
for (var i = 0, iMax = aFormFields.length; i < iMax; i++) {
var aFieldNameParts = aFormFields[i].getAttribute('name').split(".");
var oFieldValue = oResponse;
for(var j=0; j<aFieldNameParts.length; j++) {
oFieldValue = oFieldValue[aFieldNameParts[j]];
}
var sFieldValue = oFieldValue;
}
Note: if a property does not exist, an error will occur. You might want to check whether oFieldValue[ aFieldNameParts[j] ] exists or not.
While it is possible, I wouldn't loop over the input fields, but over the JSON object:
function fillForm (form, data, prefix) {
prefix = prefix ? prefix + "." : "";
for (var x in data) {
if (typeof data[x] === "string") {
var input = form.elements[prefix + x];
if (input)
input.value = data[x];
} else
fillForm(form, data[x], prefix + x);
}
}
fillForm(document.getElementById("myform"), oResponse);
(untested)
Assuming your naming scheme is consistent, you can convert the dot-notation into subscripts. You'd have to split the field name on the period and iterate or recurse over the tokens, converting each into a subscript. Of course this assumes that oResponse always contains a value for every field.
for (var i = 0; i < aFormFields.length; i++) {
var sFieldName = aFormFields[i].getAttribute('name');
var tokens = sFieldName.split('.');
var cur = oResponse;
for (var j = 0; j < tokens.length; j++) {
cur = cur[tokens[j]];
}
sFieldValue = cur;
}
please treat this as a combination of answer and question :)
i am currently trying to get my server to jsonify the data that i get sent from a form just like you...
in my case the form will in the end create a json object with multiple subobjects that can have subobjects which can have... as well.
the depth is up to the user so i should be able to support infinite recursion.
my "solution" so far just feels wrong, but it correctly does the job,
the function getRequestBody gets fed a req.body object from expressjs,
this is basically an object with the following mapping:
{
"ridic-ulously-deep-subobject": "value",
"ridic-ulously-deep-subobject2": "value",
"ridic-ulously-deep2-subobject3": "value",
}
the following html is in use:
<form>
<input name="ridic-ulously-long-class-string" value="my value" />
</form>
and the javascript function (that should work genericly, feed it a req.body object like above and it will return a json object):
function getRequestBody(reqB){
var reqBody = {};
for(var keys in reqB) {
var keyArr = keys.split('-');
switch(keyArr.length){
case 1:
if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
reqBody[keyArr[0]] = reqB[keys];
break;
case 2:
if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};
reqBody[keyArr[0]][keyArr[1]] = reqB[keys];
break;
case 3:
if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};
if(!reqBody[keyArr[0]][keyArr[1]][keyArr[2]]) reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = {};
reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = reqB[keys];
break;
case 4:
// ...
//and so on, always one line longer
}
return reqBody;
}
this just feels wrong and its only covering 5 levels of subobjects right now,
it might happen that an application has enough functionality to reach seven or even ten levels though.
this should be a common problem, but my search effort turned up nothing within 10 minutes,
which usually means that i am missing some keywords
or
that there is no viable solution [yet] (which i cant really imagine in this case).
is there someone out there who has imagination and logic sufficient enough to unspaghettify this or will i just have to expand this function with even more clutter to get me down to 10 possible sublevels?
i think that in the end it wont make a big difference performance wise,
but i would really like NOT to create this awful behemoth :D
have fun
jascha

Categories

Resources