I am sending some request on a server and it's reply me this:
{"COLUMNS":["REGISTRATION_DT","USERNAME","PASSWORD","FNAME","LNAME","EMAIL","MOBILE","FACEBOOK_ID"],"DATA":[["March, 17 2012 16:18:00","someuser",somepass,"somename","somesur","someemail",sometel,"someid"]]}
I tried a lot but nothing seems to working for me!
var xml2 = this.responseData;
var xml3 = xml2.getElementsByTagName("data");
Ti.API.log(xml3.FNAME);
For this code I get "null".
Any help would be appreciated!
If you're trying to use JSON format, your problem is that the data within the [...] also needs to be in pairs, and grouped in {...} like here.
For instance,
{
"sales": [
{ "firstname" : "John", "lastname" : "Brown" },
{ "firstname" : "Marc", "lastname" : "Johnson" }
] // end of sales array
}
So you might have:
{"COLUMNS": [
{"REGISTRATION_DT" : "19901212", "USERNAME" : "kudos", "PASSWORD" : "tx91!#1", ... },
{"REGISTRATION_DT" : "19940709", "USERNAME" : "jenny", "PASSWORD" : "fxuf#2", ... },
{"REGISTRATION_DT" : "20070110", "USERNAME" : "benji12", "PASSWORD" : "rabbit19", ... }
]
}
If the server is sending you something which you refer to as res, you can just do this to parse it in your Javascript:
var o=JSON.parse(res);
You can then cycle through each instance within columns like follows:
for (var i=0;i<o.COLUMNS.length;i++)
{
var date = o.COLUMNS[i].REGISTRATION_DT; ....
}
see that link. READ JSON RESPONSE
It's perfect.
JSON objects work just like any normal javascript objects or dictionaries
// You can do it this way
var data = this.responseData["DATA"]
// Or this way
var data = this.responseData.DATA
In your case, COLUMNS and data are both arrays, so it looks like you're trying to get the element from data that corresponds to the "FNAME" element in COLUMNS?
var columns = this.responseData["COLUMNS"];
var data = this.responseData["DATA"][0];
for(var i=0; i<columns.length; i++){
if(columns[i] == "FNAME"){
Ti.API.log(data[i]);
}
}
EDIT: If you can't change the data on the server end, you can make your own object client side. This also helps if you have to refer to multiple columns (which you probably do).
var columns = this.responseData["COLUMNS"];
var data = this.responseData["DATA"][0];
var realData = {};
for(var i=0; i<columns.length; i++){
realData[columns[i]] = data[i];
}
// Now you can access properties directly by name.
Ti.API.log(data.FNAME);
More edit:
My answers only consider the first row in DATA, because I misread originally. I'll leave it up to you to figure out how to process the others.
If you got here trying to find out how to read from [Response object] (as I did) -
this what can help:
- if you use fetch don't forget about res.json() before logging in console
fetch(`http://localhost:3000/data/${hour}`, {
method: 'get'
})
.then(res => {
return res.json()
})
.then((response) => {
console.log('res: ' + JSON.stringify(response))
})
Testing out your code in http://jsonlint.com/, it says that your server's response is not a valid JSON string.
Additionally, I recommend checking out jQuery.parseJSON http://api.jquery.com/jQuery.parseJSON/
Just use JSON.parse(serverResponse)
Related
Using the api I was able to retrieve the info i needed trough the following endpoints and create the following object.
var lego = {
"name" : item.name,
"followers" : item.follower_count,
"created" : item.created_at,
"updated" : item.updated_at
}
<datagrid id = "topicGrid" data='[{}]'>
<datagrid-column head="Topic" content-key="name"></datagrid-column>
<datagrid-column head="Followers" content-key="followers"></datagrid-column>
<datagrid-column-time head="Created" content-key="created" format="date"></datagrid-column-time>
<datagrid-column-time head="Updated" content-key="updated" format="date"></datagrid-column-time>
</datagrid>
I would like to somehow append the "lego" object in the new data attribute ?
Now i tried something like
setAttribute("data", lego); but my knowledge here is limited.
Any help is apreciated. Thank you.
Update:
I tried passing the object as a string but I only get the last element of the object. Kind of like it's looping trough the whole object and stopping at the last one.
$('datagrid').attr('data', JSON.stringify(lego));
My solution
$.get( "..." ).done(function( data ) {
var legoArr = []
$.each(data.topics, function(index,item) {
var lego = {
"name" : item.name,
"followers" : item.follower_count,
"created" : item.created_at,
"updated" : item.updated_at
};
legoArr.push(lego);
});
$('datagrid').attr('data', JSON.stringify(legoArr));
});
Introduction
I'm learning JavaScript on my own and JSON its something along the path. I'm working on a JavaScript WebScraper and I want, for now, load my results in JSON format.
I know I can use data base, server-client stuff, etc to work with data. But I want to take this approach as learning JSON and how to parse/create/format it's my main goal for today.
Explaining variables
As you may have guessed the data stored in the fore mentioned variables comes from an html file. So an example of the content in:
users[] -> "Egypt"
GDP[] -> "<td> $2,971</td>"
Regions[] -> "<td> Egypt </td>"
Align[] -> "<td> Eastern Bloc </td>"
Code
let countries = [];
for(let i = 0; i < users.length; i++)
{
countries.push( {
'country' : [{
'name' : users[i],
'GDP' : GDP[i],
'Region' : regions[i],
'Align' : align[i]
}]})
};
let obj_data = JSON.stringify(countries, null, 2);
fs.writeFileSync('countryballs.json', obj_data);
Code explanation
I have previously loaded into arrays (users, GDP, regionsm align) those store the data (String format) I had extracted from a website.
My idea was to then "dump" it into an object with which the stringify() function format would format it into JSON.
I have tested it without the loop (static data just for testing) and it works.
Type of error
let obj_data = JSON.stringify(countries, null, 2);
^
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Node'
| property 'children' -> object with constructor 'Array'
| index 0 -> object with constructor 'Node'
--- property 'parent' closes the circle
What I want from this question
I want to know what makes this JSON format "Circular" and how to make this code work for my goals.
Notes
I am working with Node.js and Visual Studio Code
EDIT
This is further explanation for those who were interested and thought it was not a good question.
Test code that works
let countries;
console.log(users.length)
for(let i = 0; i < users.length; i++)
{
countries = {
country : [
{
"name" : 'CountryTest'
}
]
}
};
let obj_data = JSON.stringify(countries, null, 2);
fs.writeFileSync('countryballs.json', obj_data);
});
Notice in comparison to the previous code, right now I am inputing "manually" the name of the country object.
This way absolutely works as you can see below:
Now, if I change 'CountryTest' to into a users[i] where I store country names (Forget about why countries are tagged users, it is out of the scope of this question)
It shows me the previous circular error.
A "Partial Solution" for this was to add +"" which, as I said, partially solved the problem as now there is not "Circular Error"
Example:
for(let i = 0; i < users.length; i++)
{
countries = {
country : [
{
"name" : users[i]+''
}
]
}
};
Resulting in:
Another bug, which I do not know why is that only shows 1 country when there are 32 in the array users[]
This makes me think that the answers provided are not correct so far.
Desired JSON format
{
"countries": {
"country": [
{
"name": "",
"GDP" : "",
"Region" : "",
"Align" : ""
},
{
"name": "",
"GDP" : "",
"Region" : "",
"Align" : ""
},
{
"name": "",
"GDP" : "",
"Region" : "",
"Align" : ""
}
]}
}
Circular structure error occurs when you have a property of the object which is the object itself directly (a -> a) or indirectly (a -> b -> a).
To avoid the error message, tell JSON.stringify what to do when it encounters a circular reference. For example, if you have a person pointing to another person ("parent"), which may (or may not) point to the original person, do the following:
JSON.stringify( that.person, function( key, value) {
if( key == 'parent') { return value.id;}
else {return value;}
})
The second parameter to stringify is a filter function. Here it simply converts the referred object to its ID, but you are free to do whatever you like to break the circular reference.
You can test the above code with the following:
function Person( params) {
this.id = params['id'];
this.name = params['name'];
this.father = null;
this.fingers = [];
// etc.
}
var me = new Person({ id: 1, name: 'Luke'});
var him = new Person( { id:2, name: 'Darth Vader'});
me.father = him;
JSON.stringify(me); // so far so good
him.father = me; // time travel assumed :-)
JSON.stringify(me); // "TypeError: Converting circular structure to JSON"
// But this should do the job:
JSON.stringify(me, function( key, value) {
if(key == 'father') {
return value.id;
} else {
return value;
};
})
The answer is from StackOverflow question,
Stringify (convert to JSON) a JavaScript object with circular reference
From your output, it looks as though users is a list of DOM nodes. Rather than referring to these directly (where there are all sort of possible cyclical structures), if you just want their text, instead of using users directly, try something like
country : [
{
"name" : users[i].textContent // maybe also followed by `.trim()
}
]
Or you could do this up front to your whole list:
const usersText = [...users].map(node => node.textContent)
and then use usersText in place of users as you build your object.
If GDP, regions and align are also references to your HTML, then you might have to do the same with them.
EUREKA!
As some of you have mentioned above, let me tell you it is not a problem of circularity, at first..., in the JSON design. It is an error of the data itself.
When I scraped the data it came in html format i.e <td>whatever</td>, I did not care about that as I could simply take it away later. I was way too focused in having the JSON well formatted and learning.
As #VLAZ and #Scott Sauyezt mentioned above, it could be that some of the data, if it is not well formatted into string, it might be referring to itself somehow as so I started to work on that.
Lets have a look at this assumption...
To extract the data I used the cheerio.js which gives you a kind of jquery thing to parse html.
To extract the name of the country I used:
nullTest = ($('table').eq(2).find('tr').eq(i).find('td').find('a').last());
//"Partial solution" for the OutOfIndex nulls
if (nullTest != null)
{
users.push(nullTest);
}
(nullTest helps me avoid nulls, I will implement some RegEx when everything works to polish the code a bit)
This "query" would output me something like:
whatEverIsInHereIfThereIsAny
or else.
to get rid off this html thing just add .html() at the end of the "jquery" such as:
($('table').eq(2).find('tr').eq(i).find('td').find('a').last().html());
That way you are now working with String and avoiding any error and thus solves this question.
Objects thats returned:
ref.orderByChild('name').once('value').then(function(snapshot){
var results = snapshot.val();
When i log results the image is what i get, Ive been trying to access the value of 'active' for each of the three objects, phishing, information and techniques.
This is my first JS application sorry if its an easy one but couldn't find an answer else where that worked.
There are two (common) ways to do this: the Firebase way and the regular JavaScript way.
the Firebase way
Since it seems you're returning a list of nodes, I'll start with the Firebase way.
ref.orderByChild('name').once('value').then(function(snapshot){
var actives = {};
snapshot.forEach(function(childSnapshot) {
var result = childSnapshot.val();
var key = result.key;
var active = result.active;
actives[key] = active;
}
console.log(actives);
}
So we're using Firebase's Snapshot.forEach() method here to loop over the child nodes.
the regular JavaScript way
Alternatively you can get the value of the entire snapshot as you already do and use plain old JavaScript to get the result you need. Jatin's answer shows one way to do that, but here's another:
ref.orderByChild('name').once('value').then(function(snapshot){
var results = snapshot.val();
var keys = Object.keys(results); // ["information", "phishing", "techniques"]
var actives = {};
keys.forEach(function(key) {
actives[key] = results[key].active;
});
console.log(actives);
}
So in this case we're using Object.keys() to get the child node names and then loop over that array with JavaScript's Array.forEach().
var snapshot = {
"information" : {
"active" : "y",
"name" : "information"
},
"phishing" : {
"active" : "z",
"name" : "phishing"
},
"techniques" : {
"active" : "x",
"name" : "techniques"
},
};
console.log(snapshot.information.active);
console.log(snapshot.phishing.active);
console.log(snapshot.techniques.active);
this is basic string response :
response = "[{"prefixtodomid":"Sat17Dec2016103310GMT","todo_title":"task 3 changed","is_done_todo":false,"todo_subtitle_field":"\u00a0","prefix_pro_due_date":"","multicheckbox":false,"project_file_list":""},{"prefixtodomid":"Sat17Dec2016103313GMT","todo_title":"ce","is_done_todo":false,"todo_subtitle_field":"\u00a0","prefix_pro_due_date":"","multicheckbox":false,"project_file_list":""},{"prefixtodomid":"Sat17Dec2016103318GMT","todo_title":"dewdw","is_done_todo":false,"todo_subtitle_field":"\u00a0","prefix_pro_due_date":"","multicheckbox":false,"project_file_list":""},{"prefixtodomid":"Sat17Dec2016103321GMT","todo_title":"task 4","is_done_todo":false,"todo_subtitle_field":"\u00a0","prefix_pro_due_date":"","multicheckbox":false,"project_file_list":""},{"prefixtodomid":"Sat17Dec2016181953GMT","todo_title":"task 5","is_done_todo":false,"todo_subtitle_field":"\u00a0","prefix_pro_due_date":"","multicheckbox":false,"project_file_list":{"43":"http:\/\/example\/intra\/wp-content\/uploads\/2016\/11\/1project.png","26":"http:\/\/example\/intra\/wp-content\/uploads\/2016\/11\/2016--\u2039-Le-Blog-OSD-\u2014-WordPress_437.png"}},{"prefixtodomid":"Sat17Dec2016181957GMT","todo_title":"cewcwcwecw","todo_subtitle_field":"\u00a0","project_file_list":{"26":"http:\/\/example\/intra\/wp-content\/uploads\/2016\/11\/2016-10-16-15_26_04-Unyson-\u2039-Le-Blog-OSD-\u2014-WordPress_437.png"}}]"
i parsed it to json like :
var obj = jQuery.parseJSON( response );
now i am looping through this :
for (var i = 0; i<Object.keys(obj).length; i++) {
(function(index){
var haveimage = obj[i].project_file_list;
if(haveimage){
// other logic
}
})(i); // pass the value of i
}
here haveimage is showing image always in order of id of image , even if we change order in response string , parseJSON method just change order by id again , is there any solution to overcome this ?
if not is there anything else i can use instead of parseJSON ?
Thank you :)
An object is an unordered set of name/value pairs.
You can use array to maintain the order:
[
{
"43":"http:\/\/example\/intra\/wp-content\/uploads\/2016\/11\/1project.png"
},
{
"26":"http:\/\/example\/intra\/wp-content\/uploads\/2016\/11\/2016--\u2039-Le-Blog-OSD-\u2014-WordPress_437.png"
}
]
I am using wikipedia API my json response looks like,
"{
"query": {
"normalized": [
{
"from": "bitcoin",
"to": "Bitcoin"
}
],
"pages": {
"28249265": {
"pageid": 28249265,
"ns": 0,
"title": "Bitcoin",
"extract": "<p><b>Bitcoin</b>isapeer-to-peerpaymentsystemintroducedasopensourcesoftwarein2009.Thedigitalcurrencycreatedandlikeacentralbank,
andthishasledtheUSTreasurytocallbitcoinadecentralizedcurrency....</p>"
}
}
}
}"
this response is coming inside XMLHTTPObject ( request.responseText )
I am using eval to convert above string into json object as below,
var jsonObject = eval('(' +req.responseText+ ')');
In the response, pages element will have dynamic number for the key-value pair as shown in above example ( "28249265" )
How can I get extract element from above json object if my pageId is different for different results.
Please note, parsing is not actual problem here,
If Parse it , I can acess extract as,
var data = jsonObject.query.pages.28249265.extract;
In above line 28249265 is dynamic, This will be something different for different query
assuming that u want to traverse all keys in "jsonObject.query.pages".
u can extract it like this:
var pages = jsonObject.query.pages;
for (k in pages) { // here k represents the page no i.e. 28249265
var data = pages[k].extract;
// what u wana do with data here
}
or u may first extract all page data in array.
var datas = [];
var pages = jsonObject.query.pages;
for (k in pages) {
datas.push(pages[k].extract);
}
// what u wana do with data array here
you can archive that using two methods
obj = JSON.parse(json)
OR
obj = $.parseJSON(json);
UPDATE
Try this this
var obj = JSON.parse("your json data string");
//console.log(obj)
jQuery.each(obj.query.pages,function(a,val){
// here you can get data dynamically
var data = val.extract;
alert(val.extract);
});
JSBIN Example
JSBIN