How can I transform the data received in CSDL format from an Oracle DB to JSON format in NODE JS
export async function getRecepFarma(req: Request, res: Response): Promise<Response> {
const conn = await connect();
const result = await conn.execute(
`SELECT * FROM IVMOV`
)
return res.json(result);
}
enter image description here
The driver is not returning CSDL format unless that's just a coincidence. The driver returns a JavaScript object with properties, such as metadata (with info about the columns) and rows (the actual data).
The easiest way to convert a JavaScript object to JSON is with JSON.stringify(object). However, you're calling res.json, which will do this for you. If you just want to send the data as JSON, you can call return res.json(result.rows);.
The resulting JSON will be an array of arrays by default. However, if you want an array of objects, then you can the outFormat property, either at the global level (oracledb) or as an execute option.
Here's your code modified to do that:
export async function getRecepFarma(req: Request, res: Response): Promise<Response> {
const conn = await connect();
const result = await conn.execute(
`SELECT * FROM IVMOV`,
[], // no binds
{
outFormat: oralcedb.OUT_FORMAT_OBJECT
}
)
return res.json(result);
}
If you want to stream a large result set, rather than use the buffered rows property, then that does take just a little more code. Let me know if that's something you need.
Finally, you might find this series on creating a REST API with Node.js and Oracle Database useful:
https://jsao.io/2018/03/creating-a-rest-api-with-node-js-and-oracle-database/
Related
Here's the error I'm getting => "TypeError: apartment.lean is not a function"
In this code, I get an error which says lean() is not a function:
let apartment = await Apartment.findOne({
'address.placeId':req.body.placeId,
'address.apartmentNumber':req.body.apartmentNumber
});
if(apartment){
//fetch references of pictures belonging to the apartment and send them back to the user
const pictureReferences = fetchPictureReferences(apartment._id);
let apartmentPoJo = apartment.lean();
apartmentPoJo.pictures=[...pictureReferences];
return res.status(200).json({msg:'Apartment Found',apartment:apartmentPoJo});
}
In that code, it runs fine, basically calling the lean() function right after the findOne() finishes:
let apartment = await Apartment.findOne({
'address.placeId':req.body.placeId,
'address.apartmentNumber':req.body.apartmentNumber
}).lean();
if(apartment){
//fetch references of pictures belonging to the apartment and send them back to the user
const pictureReferences = fetchPictureReferences(apartment._id);
apartment.pictures=[...pictureReferences];
return res.status(200).json({msg:'Apartment Found',apartment});
}
Can you let me know why they're different ? I'm assuming that the findOne() function returns a document. Whether I execute it on the spot or on the new variable that I created no ?
Thanks for the clarification!
In short, lean is only a method of the Model (or Query) class. The returned Document class DOES NOT have the lean method.
Models and Documents are both Mongoose classes, but they're not the same. Calling a Query method (like findOne) on a Model returns an instance of a Document.
Document Methods
Model Methods
Query Methods (most of these methods are a part of the Model class)
const findApartment = async (req, res) => {
try {
const { apartmentNumber, placeId } = req.body;
if (!apartmentNumber || !placeId) throw String("You must supply a valid apartment and id!");
/*
Using the Apartment model, we invoke Query methods "findOne" and "lean".
The result of these two queries is a document instance transformed into
a plain Javascript object (a plain object where Mongoose virtuals are removed)
If you ran the query without invoking "lean", then "findOne"
would return an instance of a Document, which contain the methods
associated with Documents -- as shown above, the Document class does not
contain the "lean" method.
*/
const apartment = await Apartment.findOne({
'address.placeId': placeId,
'address.apartmentNumber': apartmentNumber
}).lean();
if (!apartment) throw String("Unable to locate the apartment with that address!");
return res.status(200).json({msg: 'Apartment Found', apartment });
} catch (err) {
return res.status(404).json({ msg: err.toString() });
}
};
The confusing part may come from the fact that Model and Document may share the same method names (like populate: D, M), but they're not the same.
More info about lean can be found here.
I am trying to send a JSON file and an image file together to a server, but am really struggling.
1) If I send just the quilt item, so skipping the formData and changing the $http part below to $http.post('quilts/create/', quilt), then set the server end point to expect (#RequestBody QuiltRequest quiltRequest) without the bits about transformRequest and headers, it processes the data therein quite happily but I don't have an image to add to the records.
2) If I don't add the quilt item to the formData, and tell the server to expect (#RequestParam("image") MultipartFile image), I can save the image file on my server and generate a url string for it, but have no other quilt information to make the corresponding database entry.
How can I send both the quilt and the image in one request, and have the server receive and process both?
Many thanks!
Client-side service:
this.create = function (quilt, image) {
quilt.size = JSON.parse(quilt.size);
quilt.maker = JSON.parse(quilt.maker);
const formData = new FormData();
formData.append('quiltRequest', quilt);
formData.append('image', image);
$http.post('quilts/create/', formData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function (response) {
return window.location = '#!/quilts/created/' + response.data;
})
};
Server-side end point:
#PostMapping(path = "/create")
public BigInteger create(#RequestPart QuiltRequest quiltRequest, #RequestPart MultipartFile image) throws IOException {
// do stuff based on parameters received
}
Apart of it, i think you can try to encode the image to base64 string. Send it to server and at the server, You decode it
My required solution have given by a real-world hero, and is posted here in case anyone else with a similar problem stumbles upon this thread :) (But thank you to user3562932 for taking some time to read and make a suggestion).
On the client side, we have moved the five lines of data preparation into a separate method, such that the original create() now takes a bunch of parameters and jumps straight to $http.post(url, data which has been magically transformed into something appropriate to send {rules on how to send the data}).
$http.post('quilts/create/', formData(quilt, image), {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function (response) {
return window.location = '#!/quilts/created/' + response.data;
})
The magical transformation happens in new function formData(), which takes as its parameters the data we want to send and makes the necessary changes:
1) make a formData container for the data to be POSTed.
2) stringify information from the html form (e.g. text, numbers) into a JSON and append to formData.
2a) in this particular case, my quilt structure contains size and maker details which arrived from the backend as JSONs, and were selected in the webpage from drop-down lists of various sizes and makers, hence the parsing rows to get these items ready to be included in the formData.
3) convert files into BLOBs, and then likewise append.
4) return formData, with all required information neatly wrapped up and ready to go!
Note: in the services.js file, this formData() method actually appears above the create() method, but it feels more logical to talk about them this way around.
function formData(quilt, image) {
let formData = new FormData();
quilt.size = JSON.parse(quilt.size);
quilt.maker = JSON.parse(quilt.maker);
formData.append('quiltRequest', JSON.stringify(quilt));
formData.append('image', new Blob([image]));
return formData;
}
On the server side, we can now happily receive this through:
#PostMapping(path = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public BigInteger create(#RequestParam(value = "quiltRequest") String quiltRequest,
#RequestParam(value = "image") MultipartFile image) throws IOException {
QuiltRequest quilt = new ObjectMapper().readValue(quiltRequest, QuiltRequest.class);
QuiltResponse quiltResponse = quiltService.create(quilt, image);
return quiltResponse.getQuilt().getId();
}
In order to enable the end point to consume our exciting multimedia input, we have to add the following import at the top of the class:
import org.springframework.http.MediaType;
We use another import to enable the use of the MultipartFile class that we have designated for the incoming image file:
import org.springframework.web.multipart.MultipartFile;
The JSON object from the webpage has come through as a String, but that needs to be parsed into its underlying components to actually be of use. This is where the ObjectMapper comes into play. Call on its readValue() method, and pass in the string argument plus a template of what the information should look like when unwrapped (here, a QuiltRequest class with defined properties corresponding to the information we fed into the JSON back in the client-end server). Remember to include the necessary import to access the ObjectMapper:
import com.fasterxml.jackson.databind.ObjectMapper;
Hopefully this breakdown of the changes makes sense, with enough explanation to help other developers build end-to-end POST requests to suit their own projects.
I'm working on AngularJS app.
Module I'm currently working on should be able to either show a preview of a spreadsheet file or allow to download it.
The steps:
When clicked on "Preview File" it should send request with needed file's name as a parameter of POST request.
Backend will find neede file, which is a .csv file, convert it to byte array type and send it to frontend.
Frontend should handle this byte array and convert it to .xls or .xlsx filetype
The spreadsheet data should be opened in some small preview read-only window, like 1000x1000 px.
The POST request line looks like that:
this.$http.post(this.url + 'endpoint/getFile', params,
{responseType: "arraybuffer", showLoadingOverlay: true}
)
The response looks indeed like ArrayBuffer: three of it in one object, i.e. Uint8Array, Uint16Array and Uint32Array.
The code which should read this and convert to content suitable for preview is not working:
const byteArray = new Uint8Array(data);
const blob = new Blob([byteArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const objectUrl = URL.createObjectURL(blob);
this.$window.open(objectUrl, 'C-Sharpcorner', 'width=1000,height=1000');
Because when created the blob, it already has 0 length in bytes, so there's no data inside.
The matter of visualising the .xls in browser window, I think, can be achieved with canvas-datagrid library. Haven't used but it looks cool.
Also, I have a problem with trying to set up a mock data for node.js (and AngularMock), for local testing when there's no data on a java backend.
I'm using 'fs' and 'csv-parse':
const fs = require('fs');
const csvParse = require("csv-parse/lib/es5");
module.exports = function stir(app) {
const getFile = () => {
const csvOutput = csvParse('../static/someData.csv', (parsed) => {
return parsed;
});
fs.readFileSync(csvOutput);
};
app.post('/stir/getFile', (req, res) => res.json(getFile()));
};
Which results in error:
TypeError: path must be a string or Buffer
What is the proper way of parsing the .csv using 'csv-parse' and sending parsed data as an ArrayBuffer to frontend in Node and AngularMock?
csv-parse docs are telling that underneath, the lib will convert the parsed object to node stream.
So why that error happens?
I am trying to develop an app for my fantasy baseball league to use for our draft (we some kind of quirky stuff all the major sites don't account for) - I want to pull some player data to use for the app by using MLB's API. I have been able to get the response from MLB, but can't do anything with the data after I get it back. I am trying to store the JSON into an array, and if I console.log the array as a whole, it will give me the entire chunk of data, but if I try to call the specific index value of the 1st item, it comes back as undefined.
let lastName = 'judge';
let getData = new XMLHttpRequest;
let jsonData = [];
function getPlayer () {
getData.open('GET', `http://lookup-service-
prod.mlb.com/json/named.search_player_all.bam?
sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`, true)
getData.onload = function() {
if (this.status === 200) {
jsonData.push(JSON.parse(this.responseText));
}
}
getData.send();
console.log(jsonData);
}
When I change the above console.log to console.log(jsonData[0]) it comes back as undefined. If I go to the console and copy the property path, it displays as [""0""] - Either there has to be a better way to use the JSON data or storing it into an array is doing something abnormal that I haven't encountered before.
Thanks!
The jsonData array will be empty after calling getPlayer function because XHR loads data asynchronously.
You need to access the data in onload handler like this (also changed URL to HTTPS to avoid protocol mismatch errors in console):
let lastName = 'judge';
let getData = new XMLHttpRequest;
let jsonData = [];
function getPlayer () {
getData.open('GET', `https://lookup-service-
prod.mlb.com/json/named.search_player_all.bam?
sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`, true)
getData.onload = function() {
if (this.status === 200) {
jsonData.push(JSON.parse(this.responseText));
// Now that we have the data...
console.log(jsonData[0]);
}
}
getData.send();
}
First answer from How to force a program to wait until an HTTP request is finished in JavaScript? question:
There is a 3rd parameter to XmlHttpRequest's open(), which aims to
indicate that you want the request to by asynchronous (and so handle
the response through an onreadystatechange handler).
So if you want it to be synchronous (i.e. wait for the answer), just
specify false for this 3rd argument.
So, you need to change last parameter in open function as below:
getData.open('GET', `http://lookup-service-
prod.mlb.com/json/named.search_player_all.bam?
sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`, false)
But from other side, you should allow this method to act asynchronously and print response directly in onload function.
export default class App extends Component {
state = {
data: []
};
fetchData = async () => {
const response = await fetch("https://randomuser.me/api?results=5"); // Replace this with the API call to the JSON results of what you need for your app.
const json = await response.json();
this.setState({ data: json.results }); // for the randomuser json result, the format says the data is inside results section of the json.
};
So, I have this code in my App.js file for React Native. The randomuser.me is a website that just gives you random users. Using it as a test URL right now. I don't really understand what the code is doing enough to be able to use it for other parts of my project. I was able to successfully display the 5 user results but now I want to access them again and iterate through the data attribute of the state.
tldr; Can I just access the data I got from the fetch in a for loop using data[i]? Please advise. I want to see if user input matches any of the items in the response that is stored in data attribute of state.
Ok the thign that you just did, that is fetch. You retrieve data from the internet.
"https://randomuser.me/api?results=5" is an API, there is lot of different API's, and each one has it´s own way to retrieve data from. if you put "https://randomuser.me/api?results=5" in your browser, you are gonna see a JSON, some API's store data in JSON, others in an array format.
In this case, the JSON, has just one child, 'results', thats why you store "json.results".
That´s fetch. The thing that you want to do is just javascript.
Store json.results in a variable
then iterate over it
var Results = json.results //store it in a variable
for(var i = 0;i<Object.keys(Results).length;i++){ //iterate
var CurrentUser = Results[Object.keys(Results)[i]] // i use this because some JSOn have random keys
if(CurrentUser.gender==='male'){//if you meet a condition
//do whatever you want
}
}
you can also use ".map" if it´s an array