I understand there are many similar questions exist, however I couldn't find a proper answer.
Consider the Javascript object,
var a = [ { defaultCount:'200' , timeintervals : [{ day:'Weekday', from:'9:00', to:'18:00', count:'100' }, { day:'Weekday', from:'9:00', to:'18:00', count:'100' } ]}];
Now running a[0].defaultCount gives me "200" as expected.
Now the same Javascript object, I am putting inside double quotes.
var b = "[ { defaultCount:'200' , timeintervals : [{ day:'Weekday', from:'9:00', to:'18:00', count:'100' }, { day:'Weekday', from:'9:00', to:'18:00', count:'100' } ]}]";
here b[0] gives me "[" and b[4] gives me "d" so on.
If I understand correctly, var a is JavaScript Object and var b is String.
I am receiving var b from the Java side as a String.
How do I convert var b into a form that I can iterate as I do on var a ?
I have tried :
var c = JSON.parse(b) but getting syntax error.
I really do not wish to change the JSON format much as it is the template used in the Java end as well.
Are there any easy workarounds ?
console screenshot
[{
"defaultCount":"200" ,
"timeintervals": [{ "day":"Weekday", "from":"9:00", "to":"18:00", "count":"100" }, { "day":"Weekday", "from":"9:00","to":"18:00", "count":"100"}]
}]
use double quotes
Related
Thanks to the answer posted here: Put data from a csv file into an array (Javascript) I have been able to split a csv file in the manner I need to but I have come across a problem with the output. Nothing to do with the code as it works just as I wanted it to. The issue relates to the source data.
The csv files are provided to me as is so I did not realise that they had fields that contained commas. This means the split doesn't work as needed.
This is the code I am using:
$.get("export.csv", function process(dataString) {
var lines = dataString
.split(/\n/)
.map(function(lineStr) {
return lineStr.split(",");
});
var keys = lines[0];
var objects = lines
.slice(1)
.map(function(arr) {
return arr.reduce(function(obj, val, i) {
obj[keys[i]] = val;
return obj;
}, {});
});
console.log(objects);
})
This gives me the output in this format:
{
"PROBLEM_NUMBER": "ticket_number",
"CALLER_NAME": "\"surname",
"PRIORITY": " forename\"",
"CALL_TIME": "4",
"CALL_DETAILS": "date",
"RESOLVER": "group",
"RESTORING_GROUP": "\"surname",
"RESOLVING_GROUP": " forename\"",
"RESTORATION_TIME": "group",
"RAG_STATUS": "group",
"CALL_STATUS": "date",
"CALL_TYPE": "RED",
"RESTORATION_CODE": "Closed",
"SUBMITTER_GROUP": "Problem",
"ASSIGNEE_GROUP": "resolution",
"ASSIGNEE_NAME": "group",
"RESOLVED_DATE_TIME": "group",
"RESTORED_DATE_TIME": "",
"TIME_WITH_TEAM": "date",
"MONTH/YEAR\r": "date",
"undefined": "Jan-21\r"
}
As you can see, the final field is "undefined" due to 2 fields containing a comma and splitting incorrectly.
I know I need to use regex to modify the split correctly however I don't understand or know where to put it. Is anyone able to assist me please?
Thanks
I managed to solve the problem so thought I would post here for anyone else that may come across a similar issue:
To resolve it I declared the regex string as a variable and then called that in the .split() instruction.
The regex string I used was - /("[^"]+"|[^,]+)*,/g
My code now looks like this:
$.get("export.csv", function process(dataString) {
var regex = /("[^"]+"|[^,]+)*,/g;
var lines = dataString
.split(/\n/)
.map(function(lineStr) {
return lineStr.split(regex);
});
var keys = lines[0];
var objects = lines
.slice(1)
.map(function(arr) {
return arr.reduce(function(obj, val, i) {
obj[keys[i]] = val;
return obj;
}, {});
});
console.log(objects);
})
This gives me the correct output I need and maps all values accordingly
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.
I've following object that is return from API and I want to convert them into array either in javascript or c#.
[
"1":"h1:first",
"2":".content a > img",
"3":"#content div p"
]
I've tried converting that to json object, split function etc but din't working for me.
It throws exception Uncaught SyntaxError: Unexpected token : while using split function in javascript.
You can convert it to valid JSON by replacing the square brackets with curly braces.
var data = '["1":"h1:first","2":".content a > img","3":"#content div p"]';
var json = `{ ${data.trim().slice(1, -1)} }`;
Then JSON.parse it like you had tried earlier. And if you want an array, and don't care about the actual index numbers, you can use Object.values to get the Array of values.
var data = '["1":"h1:first","2":".content a > img","3":"#content div p"]';
var json = `{ ${data.trim().slice(1, -1)} }`;
console.log(json);
var parsed = JSON.parse(json);
console.log(parsed);
var array = Object.values(parsed);
console.log(array);
I choose c# code to fix the issue instead client-side (as suggested by #rock star below).
string[] domSelectors = selectors.Replace("\"", "").Split(new string[] { "[", ",", "]" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var domSelector in domSelectors)
{
string[] arrayElements = domSelector.Split(':');
string selector = string.Join(":", arrayElements.Skip(1));
}
Hope it helps others who don't have control over API and want to fix the issue as I'd in my project!
I have a doubt about how to unite to objects and give them in a express response in node js.
The object is like this:
{
"idP": 1,
"pasaporteNum": 787643682,
"fidP": 1,
"fid_p": 1
}
The other one also:
{
"idP": 1,
"pasaporteNum": 827348,
"fidP": 1,
"fid_p": 75683475
}
So the code is something like:
var a = JSON.stringify(context.instance[0].dataValues)
var b = JSON.stringify(context.instance[2].dataValues)
res.send('{'+JSON.parse(a+','+b)+'}')
Why I receive this error?
"Unexpected token , in JSON at position 53"
At the end I need something like:
{
"idP": 1,
"pasaporteNum": 787643682,
"fidP": 1,
"fid_p": 1
},
{
"idP": 4,
"pasaporteNum": 456789,
"fidP": 2,
"fid_p": 2
}
regards
Seeing as you have two objects with the same properties, you probably just want to add those to an array before stringifying
var arr = [context.instance[0].dataValues, context.instance[2].dataValues]
res.send( JSON.stringify( arr ) )
I think you want to have a JSON format and send from your api, so you need not JSON.parse() but JSON.stringify().
var a = JSON.stringify(context.instance[0].dataValues);
var b = JSON.stringify(context.instance[2].dataValues);
res.send('{' + JSON.stringify(a + ',' + b) + '}');
with your format, you want an array instead of an object .
res.send('['+JSON.parse(a+','+b)+']')
or simpler you can do
JSON.stringify([context.instance[0].dataValues,context.instance[2].dataValues])
You don't need to use .stringify() and .parse(), Just as create an array and send it.
res.send([context.instance[0].dataValues, context.instance[2].dataValues])
The code:
function updateDashboardData() {
$.getJSON("includes/system/ajaxDataInterface.php", {recordcount:1}, function(data) {
$('.stationContainer').each(function(data) {
var bsID = $(this).attr("id");
var bsStatus = $(this).children('.stationStatus');
alert(data[bsID][0].time);
bsStatus.find('.bs_maxHandsets').text(data[bsID][0].maxHandsets);
bsStatus.find('.bs_time').text(data[bsID][0].time);
});
});
}
The object data:
{
"A5A50000": [{
"bsid": "A5A50000",
"chanCount": 17,
"time": "2009-05-27 16:36:45",
"avgInterference": 1.711765,
"maxInterference": 4.97,
"avgHandsets": 205.1176,
"maxHandsets": 315,
"avgCalls": 6.4118,
"maxCalls": 13,
"avgCBA": 3868.98059,
"maxCBA": 7463,
"sumSuccessCBA": 197318,
"sumTimeoutHandoff": 133,
"sumAttemptHandoff": 1028,
"sumDeniedHandoff": 216,
"sumConfirmHandoff": 679,
"sumHandoffNetwork": 61873,
"sumJoinNetwork": 96888,
"sumLeaveNetwork": 93754,
"sumRcvdKeepalive": 98773,
"sumTimeoutKeepalive": 19748,
"sumAttemptUplink": 93689,
"sumBlockedUplink": 62453
}]
}
The problem:
alert(data.A5A50000[0].time); properly displays "2009-05-27 16:36:45".
alert(bsID); properly displays "A5A50000".
alert(data.bsID[0].time); reports "data.bsID is undefined".
alert(data[bsID][0].time); reports "data[bsID] is undefined".
I'm a little unclear when a variable is/isn't evaluated. Maybe I'm overlooking something silly, but I can't figure out my problem here.
You can access object properties by dot notation or by bracket notation.
var x = {'test': 'hi'};
alert(x.test); // alerts hi
alert(x['test']); // alerts hi
When you have a dynamic value, you have to use the latter:
var property = 'test';
alert(x.property); // looks for x.property, undefined if it doesn't exist
alert(x[property]); // looks for x['test'], alerts hi
So what you actually want is:
alert(data[bsID][0].time);
EDIT:
Not sure what you're doing wrong, but this is working for me on Firebug's console:
var data = {"A5A50000":[{"bsid":"A5A50000","chanCount":17,"time":"2009-05-27 16:36:45","avgInterference":1.711765,"maxInterference":4.97,"avgHandsets":205.1176,"maxHandsets":315,"avgCalls":6.4118,"maxCalls":13,"avgCBA":3868.98059,"maxCBA":7463,"sumSuccessCBA":197318,"sumTimeoutHandoff":133,"sumAttemptHandoff":1028,"sumDeniedHandoff":216,"sumConfirmHandoff":679,"sumHandoffNetwork":61873,"sumJoinNetwork":96888,"sumLeaveNetwork":93754,"sumRcvdKeepalive":98773,"sumTimeoutKeepalive":19748,"sumAttemptUplink":93689,"sumBlockedUplink":62453}]};
var bsID = 'A5A50000';
alert(data[bsID][0].time);
In Javascript, you can use either object or array-style notation to look up an attribute. The following are equivalent:
data.A5A50000
data['A5A50000']
With the second syntax, you can use a variable in place of an object string:
data[bsID][0]
I experienced the same problem with a nested JSON API-response:
[
{
"bj_code": "2019",
"BJ_PERIODE": [
{
"nummer": 1
},
{
"nummer": 2
}
]
}
]
I could evaluate:
pm.expect(pm.response.json()[0].BJ_PERIODE[1].nummer).to.eql(2);
But working with BJ_PERIODE and nummer through a variable didn't work.
Writing it with the bracket method did work, even in this nested JSON, like this:
const periode = "BJ_PERIODE";
const nr = "nummer";
pm.expect(pm.response.json()[0][periode][1][nr]).to.eql(2);