Error when trying to read JSON array using Should, Mocha, & Supertest - json

I have the following JSON payload:
"app": {
"name": "myapp",
"version": "1.0.0",
"last_commit": {
"author_name": "Jon Snow"
"author_email": "my#email.com"
}
}
and the following .js file (using Mocha, Supertest and Should):
var supertest = require('supertest')
var should = require('should')
var server = supertest.agent('http://localhost:3001')
describe('GET /', function () {
it('should respond with JSON', function (done) {
server
.get('/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function (err, res) {
var payload = res.body.app;
payload.should.have.property("app");
payload.should.have.property("name");
payload.should.have.property("version");
payload.should.have.property("last_commit");
payload.should.have.property("last_commit.author_name");
payload.should.have.property("last_commit.author_email");
done();
});
});
});
When I test the app, I receive the following error message:
Uncaught AssertionError: expected Object {
"name": "myapp",
"version": "1.0.0",
"last_commit": Object {
"author_name": "Jon Snow"
"author_email": "my#email.com"
}
} to have property 'last_commit.author_name'
Why am I receiving an assertion error on the these lines?
payload.should.have.property("last_commit.author_name");
payload.should.have.property("last_commit.author_email");

Assertion is looking for a property called last_commit.author_name which is not present. You may want to break that into two assertions.
payload.should.have.property("last_commit");
let last_commit = payload.last_commit;
last_commit.have.property("author_name");

Related

get json object attribute with 'dot' in name

*** Problem solved : json.stringify was the problem.. much easier to handle when its gone.
var DBName = result['Document']['SW.Blocks.GlobalDB']['AttributeList']['Name'];
I have a xml file which describes a datablock from a PLC and want to get specific values with JS.
I converted it with xml2js module, so i have a json object to work with.
{
"Document": {
"Engineering": {
"$": {
"version": "V15"
}
},
"SW.Blocks.GlobalDB": {
"$": {
"ID": "0"
},
"HeaderAuthor": "",
"HeaderFamily": "",
"HeaderName": "",
"HeaderVersion": "0.1",
"Interface": {
...
...
"Name": "datentypen",
"Number": "6",
"ParameterModified": {
"_": "2018-09-05T11:49:37.0862092Z",
"$": {
"ReadOnly": "true"
}
},
}
}
I want to print out the "Name" and the "Number", which are part of the "AttributeList".
So how to handle with the "SW.Blocks.GlobalDB"?
Getting error : "TypeError: Cannot read property 'SW' of undefined"
var fs = require('fs');
var xml2js = require('xml2js');
var xml = fs.readFileSync('datentypen.xml');
var parser = new xml2js.Parser({explicitArray: false});
parser.parseString(xml, function(err, result) {
if (err) {
console.error('xml2js.parse error: ',err);
} else {
var injson = JSON.stringify(result,null,3);
console.log(injson);
// var injson2 = JSON.parse(injson);
// var DBnummer = injson.Document.SW.Blocks.GlobalDB.AttributeList["Name","Number"];
// console.log(DBNummer);
};
});
I read a lot about this theme but didnt found a concrete answer..
When i write ["SW.Blocks.GlobalDB"], an error about [ comes around.
Can you try reading the JSON array using Key-Value pair? I had similar issues but with a different programming language.

Why do I get empty reponse from this http request

I am working on my first node.js script which simply makes a http request to https://www.swapi.co/api/people/?search=Luke+ and parses the response data.
The endpoint is as follows:
var options = {
host: 'www.swapi.co',
path: `/api/people/?search=`+firstName+'+'+lastName
};
The logic is to get the data from response and parse it to a person object:
makeRequest(options, function( data, error) {
let person = data.results[0];
if (person) {
let height = person.height;
let response = person.name + " is " + height + " centimeters tall.";
callback(null, {"speech": response});
}
else {
callback(null, {"speech": "I'm not sure!"});
}
});
The definition of makerequest function is below:
function makeRequest(options, callback) {
var request = http.request(options,
function(response) {
var responseString = '';
response.on('data', function(data) {
responseString += data;
});
response.on('end', function() {
console.log('end: $$$' + responseString + '$$$');
var responseJSON = JSON.parse(responseString);
callback(responseJSON, null);
});
});
request.end();
}
When I run the script I got the error about parsing the JSON.
Unexpected end of JSON input
at Object.parse (native)
at IncomingMessage.<anonymous> (/var/task/index.js:42:37)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
I tested the endpoint using Postman and got the following JSON as response:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "https://www.swapi.co/api/planets/1/",
"films": [
"https://www.swapi.co/api/films/2/",
"https://www.swapi.co/api/films/6/",
"https://www.swapi.co/api/films/3/",
"https://www.swapi.co/api/films/1/",
"https://www.swapi.co/api/films/7/"
],
"species": [
"https://www.swapi.co/api/species/1/"
],
"vehicles": [
"https://www.swapi.co/api/vehicles/14/",
"https://www.swapi.co/api/vehicles/30/"
],
"starships": [
"https://www.swapi.co/api/starships/12/",
"https://www.swapi.co/api/starships/22/"
],
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-20T21:17:56.891000Z",
"url": "https://www.swapi.co/api/people/1/"
}
]
}
However, when I debug my code, the response data is an empty string. And that explains the JSON error.
What is wrong with my http request? Why am I not getting the correct response?
It appears that the API you are targeting only supports SSL, but Node's HTTP library only supports plain-text requests. Try using their HTTPS library instead.
var https = require('https');
var request = https.request(options, ...);
That URL you are using returns HTML by default.
Instead you need to call: https://www.swapi.co/api/people/?format=json&search=Luke+
(Note the format=json parameter)

Node.js convert XML to JSON and return it to Frontend

I am trying to convert xml data to JSON in order to return it to my Angular app.
I've been able to get data but I'm not sure how to convert and return to Angular.
I am using xml2js parser plugin to convert xml.
node.js
router.get('/courselist', (req, res, next) => {
request("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", function(error, response, body) {
console.log(body);
parser(body, function (err, result) {
res.json(response);
});
});
After parsing the output is like this:
{"gesmes:Envelope": {
"$": {
"xmlns:gesmes": "http://www.gesmes.org/xml/2002-08-01",
"xmlns": "http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
},
"gesmes:subject": [
"Reference rates"
],
"gesmes:Sender": [
{
"gesmes:name": [
"European Central Bank"
]
}
],
"Cube": [
{
"Cube": [
{
"$": {
"time": "2017-09-21"
},
"Cube": [
{
"$": {
"currency": "USD",
"rate": "1.1905"
}
},
....
{
"$": {
"currency": "JPY",
"rate": "133.86"
}
},
]
}
]
}
]
}
}
Angular service
getCourseList() {
return this._http.get('./api/course-list').map(
(res: Response) => res.json()
).catch(this.handleError);
}
When I call the endpoint in Postman I can see parsed output, but in Angular I am getting error as I am not returning JSON object.
Unexpected token < in JSON at position 0
I've been looking around SO for a solution but not been able to find any which would suit me.
Can you please advise what am I doing wrong as I am beginner with Node.js
You angular service is calling './api/course-list' which is not a valid url. And, probably you have configured your server to return index.html page for even 404 page. That's why your angular client might be getting html page, and throwing the error while parsing it into `
Hope this._http.get('/api/course-list') fixes the issue.
I managed to find a solution I changed parsing to be response.body instead of body and it formatted XML properly.
Additionally paths in node.js and angular were not same.
router.get('/course-list', (req, res, next) => {
request("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", function(error, response, body) {
var parsedBody;
var doneParsing = false;
parser(response.body, function (err, result) {
parsedBody = result;
doneParsing = true;
});
if (doneParsing === true) {
response.body = parsedBody;
}
res.json(response);
});
});

Use JSON data coming from WebApi in AngularJS application

I get some data from a WebApi, the answer (below the code to get the datas) is in JSON. But I can't access this result from angularJS. The datas look like :
{
"$id": "1",
"result": [
{
"$id": "2",
"name": "Français",
"code": "FR",
"id": 1
},
{
"$id": "3",
"name": "Néerlandais",
"code": "NL",
"id": 2
},
{
"$id": "4",
"name": "English",
"code": "EN",
"id": 3
}
]
}
But I get the error below when I try to display the result :
data.result is undefined
I get the data like this :
(function () {
angular.module('myApp')
.factory('dataService', ['$q', '$http', dataService]);
function dataService($q, $http) {
return {
initFormCustomer: initFormCustomer
};
function initFormCustomer() {
return $http({
method: 'GET',
url: 'http://localhost:123456/api/forminit/customer/',
headers: {
},
transformResponse: transformCustomer,
cache: true
})
.then(sendResponseData)
.catch(sendGetCustomerError)
}
function sendResponseData(response) {
return response.data;
}
function transformCustomer(data, headersGetter) {
var transformed = angular.fromJson(data.result);
console.log(data.result[0]);
return transformed;
}
function sendGetCustomerError(response) {
return $q.reject('Error retrieving customer(s). (HTTP status: ' + response.status + ')');
}
}
}());
The controller :
(function () {
angular.module('myApp')
.controller('customerController', ['$location', '$scope', 'dataService', CustomerController]);
function CustomerController($location, $scope, dataService) {
var vm = this;
vm.languages = dataService.initFormCustomer();
}
}());
I think the transform function gets a json string that you have to deserialize before using it as an object... try sth like:
function transformCustomer(data, headersGetter) {
var transformed = angular.fromJson(data);
console.log(transformed.result[0]);
return transformed.result;
}
Additionally you may look at the docs https://docs.angularjs.org/api/ng/service/$http . There is some code showing how to append a transform to the default one (that do the deserialization and XSRF checks)

express.js 4 JSON parsing problems from GET request (request data from datatables)

I am having problems parsing a serialized JSON Ajax Get request (using jQuery $.ajax) send to my express.js 4 server. The data send as a JSON request is generated by datatables.
Here is how I started on the client-side
$(document).ready(function() {
$('#example').dataTable( {
"bServerSide": true,
"fnServerData": function (sSource, aoData, fnCallback) {
$.ajax({
"dataType": 'json',
contentType: 'application/json',
"type": "GET",
"url": "http://localhost:3000/ajax/phenotypes/withOrg/like/datatables/",
"data": aoData,
"success": fnCallback,
"error": function () {
alert('have some problem');
}
});
}
} );
} );
when I load this code in the brower datatables generates the following GET request URL (to the server):
GET
/ajax/phenotypes/withOrg/like/datatables/?draw=1&columns=%5Bobject+Object%5D%2C%5Bobject+Object%5D%2C%5Bobject+Object%5D%2C%5Bobject+Object%5D%2C%5Bobject+Object%5D%2C%5Bobject+Object%5D&order=%5Bobject+Object%5D&start=0&length=10&search=%5Bobject+Object%5D
or in decoded form (output from firebug)
columns [object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
draw 1
length 10
order [object Object]
search [object Object]
start 0
so I serialized the data before sending
$(document).ready(function() {
$('#example').dataTable( {
"bServerSide": true,
"fnServerData": function (sSource, aoData, fnCallback) {
var myData = JSON.stringify(aoData);
$.ajax({
"dataType": 'json',
contentType: 'application/json',
"type": "GET",
"url": "http://localhost:3000/ajax/phenotypes/withOrg/like/datatables/",
"data": myData,
"success": fnCallback,
"error": function () {
alert('have some problem');
}
});
}
} );
} );
here is the generated GET parameters from datatables:
GET
/ajax/phenotypes/withOrg/like/datatables/?[{%22name%22:%22draw%22,%22value%22:1},{%22name%22:%22columns%22,%22value%22:[{%22data%22:0,%22name%22:%22%22,%22searchable%22:true,%22orderable%22:true,%22search%22:{%22value%22:%22%22,%22regex%22:false}},{%22data%22:1,%22name%22:%22%22,%22searchable%22:true,%22orderable%22:true,%22search%22:{%22value%22:%22%22,%22regex%22:false}},{%22data%22:2,%22name%22:%22%22,%22searchable%22:true,%22orderable%22:true,%22search%22:{%22value%22:%22%22,%22regex%22:false}},{%22data%22:3,%22name%22:%22%22,%22searchable%22:true,%22orderable%22:true,%22search%22:{%22value%22:%22%22,%22regex%22:false}},{%22data%22:4,%22name%22:%22%22,%22searchable%22:true,%22orderable%22:true,%22search%22:{%22value%22:%22%22,%22regex%22:false}},{%22data%22:5,%22name%22:%22%22,%22searchable%22:true,%22orderable%22:true,%22search%22:{%22value%22:%22%22,%22regex%22:false}}]},{%22name%22:%22order%22,%22value%22:[{%22column%22:0,%22dir%22:%22asc%22}]},{%22name%22:%22start%22,%22value%22:0},{%22name%22:%22length%22,%22value%22:10},{%22name%22:%22search%22,%22value%22:{%22value%22:%22%22,%22regex%22:false}}]
HTTP/1.1
in decoded form (output from firebug and beautified using an online tool- checked with jslint, seems correct!)
[
{
"name":"draw",
"value":1
},
{
"name":"columns",
"value":[
{
"data":0,
"name":"",
"searchable":true,
"orderable":true,
"search":{
"value":"",
"regex":false
}
},
{
"data":1,
"name":"",
"searchable":true,
"orderable":true,
"search":{
"value":"",
"regex":false
}
},
{
"data":2,
"name":"",
"searchable":true,
"orderable":true,
"search":{
"value":"",
"regex":false
}
},
{
"data":3,
"name":"",
"searchable":true,
"orderable":true,
"search":{
"value":"",
"regex":false
}
},
{
"data":4,
"name":"",
"searchable":true,
"orderable":true,
"search":{
"value":"",
"regex":false
}
},
{
"data":5,
"name":"",
"searchable":true,
"orderable":true,
"search":{
"value":"",
"regex":false
}
}
]
},
{
"name":"order",
"value":[
{
"column":0,
"dir":"asc"
}
]
},
{
"name":"start",
"value":0
},
{
"name":"length",
"value":10
},
{
"name":"search",
"value":{
"value":"",
"regex":false
}
}
]
the problem is now that this stringified URL can not be parsed on the express 4 server side
I use express4 req.query and url.parse method for this : http://expressjs.com/api.html#req.query
and then try to parse the received json string with the JSON.parse() method
...
var url = require('url');
...
router.get('/withOrg/like/datatables/', function (req, res) {
console.log('getting json string via req.query');
console.log(req.query);
console.log('output parsed json object using JSON.parse');
console.log(JSON.parse(req.query));
//another try
console.log('for stack overflows test 2');
console.log(url.parse(req.url, true).query);
console.log('output parsed json object using JSON.parse');
console.log(url.parse(req.url, true).query);
})
both json string output results are invalid json as you can see here and unable to parse with JSON.parse:
getting json string via req.query
{
'{"data":0,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":1,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":2,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":3,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":4,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":5,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}}':
{ '{"column":0,"dir":"asc"}': '' } }
output parsed json object using JSON.parse
getting json string via req.query
{
'{"data":0,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":1,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":2,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":3,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":4,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":5,"name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}}':
{ '{"column":0,"dir":"asc"}': '' } }
output parsed json object using JSON.parse
when I try to parse the json string I get the error from JSON.parse
SyntaxError: Unexpected token o
at Object.parse (native)
at module.exports (/Users/xxx/yyy/routes/phenotypesAJAX.js:16:19)
at Layer.handle [as handle_request] (/Users/xxx/yyy/node_modules/express/lib/router/layer.js:82:5)
at next (/Users/xxx/yyy/node_modules/express/lib/router/route.js:100:13)
Is this a bug in express 4?
I cannot see where the problem is. On the client-side the serialized datatable GET request seems valid (checked with JSLint). On the express4 server side I cannot find any other way to parse the GET request in a different way.
Thank you so much for your help,
Oliver
I have got the answer from posting this problem at the express github bugtracker.
Lesson learned:
I was thinking to complicated, express.js request methods are not written especially for a specific request format! They just use the data format which was send to them without modification!
The method I used first:
req.query
[..] only works with standard query strings, which are key=value pairs,
which the URL you gave was not.[..]
The correct method to solve my problem is:
url.parse(req.url).query
returns the complete parameter string of an URL which than has to be decoded manually:
obj = JSON.parse(decodeURIComponent(query))
Here is the full explanation:
https://github.com/strongloop/express/issues/2460