I have an URL from which I fetch json data, which has many objects within it. I want to access a specific data in a specific object in that json data.
How can I.?
Assuming you are using fetch, you can get the data like this:
fetch('yourUrl', {
method: 'GET',
headers:
{
'Content-Type': 'application/json'
}
})
.then(async (response) =>
{
const json = await response.json();
if (json)
console.log(json.YOUR_OBJECT_KEY);
return (json);
})
.catch(err => console.warn(err.message))
So, withing the then, we are decrypting the response, (response.json()) and we are getting all the information.
Depending of the json file you fetched, you can access an element by doing the json.YOUR_OBJECT_KEY (here, json is basically your json converted to be usable by JS, and YOUR_OBJECT_KEY is, well, your object key)
Related
Until recently I've been fetching XML data using the node request module, and then running that XML through an XML to JSON converter. I discovered by accident that if I set json: true as an option (even knowing the endpoint returns XML, not JSON), I was actually getting back JSON:
var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'stackoverflow question (https://stackoverflow.com/q/52609246/4070848)' } };
options.uri = 'https://api.met.no/weatherapi/locationforecast/1.9/?lat=40.597&lon=-74.26';
request(options, function (error, response, body) {
console.log(`body for ${options.uri}: ${JSON.stringify(body)}`);
});
The above call returns JSON, whereas the raw URL is actually sending XML. Sure enough, with json: false the returned data is XML:
var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'stackoverflow question (https://stackoverflow.com/q/52609246/4070848)' } };
options.uri = 'https://api.met.no/weatherapi/locationforecast/1.9/?lat=40.597&lon=-74.26';
options.json = false; // <<--- the only difference in the request
request(options, function (error, response, body) {
console.log(`body for ${options.uri}: ${body}`);
});
So I thought "that's handy", until I tried the same trick with a different URL that also returns XML, and in this case the returned data is still XML despite using the same request options:
var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'stackoverflow question (https://stackoverflow.com/q/52609246/4070848)' } };
options.uri = 'https://graphical.weather.gov/xml/SOAP_server/ndfdXMLclient.php?whichClient=NDFDgen&lat=40.597&lon=-74.26&product=time-series&temp=tempSubmit=Submit';
request(options, function (error, response, body) {
console.log(`body for ${options.uri}: ${body}`);
});
What is the difference here? How do I get the latter request to return the data in JSON format (so that I can avoid the step of converting XML to JSON myself)? Maybe the endpoint in the first example can detect that JSON is requested and it does in fact return JSON rather than XML?
EDIT weirdly, the first request is now returning XML rather than JSON even with json: true. So maybe this behaviour was down to what was being sent from the endpoint, and they've changed this even since I posted a few hours ago
So now that the behavior is unrepeatable, the answer is less useful for your particular problem, but I think it's worth pointing out that when you set json:true on the request module, it does a few things under the hood for you:
Sets the Accept header to 'application/json'
Parses the response body using JSON.parse()
Request types with a body also get the body automatically serialized as JSON
Request types with a body also get the Content-Type header added as 'application/json'
So perhaps they did change it, but there are plenty of web services I've seen that will detect the content-type to send based on the Accept header and respond appropriately for some set of types that make sense (usually XML or JSON, but sometimes CSV, TXT, HTML, etc).
To handle XML query, I usually do something like this using the request module:
import parser from "xml2json";
const resp = await rp({
method: "POST",
url: 'some url',
form: {xml_query}, // set XML query to xml_query field
});
const parsedData = parser.toJson(resp, {
object: true, // returns a Javascript object instead of a JSON string
coerce: true, // makes type coercion.
});
I'm new to REST services, I have an Angular2 client calling a RestEasy JAX-RS service. All I am trying to get is a "Hello World" message in JSON format. I was expecting only a JSON object, but I get my response with the following structure:
_body: "{"message":"Hello World!!"}"
headers: t
ok: true
status: 200
statusText: "OK"
type: 2
url: "http://localhost:8080/helloapp/rest/hello/world"
__proto__: ...
My question is, Is that the way it should be?
I mean, I thought I would be able to access the JSON object straight from the response. Something like
this.service.getHello()
.then( result => {
console.log(JSON.parse(result)); //{message: "Hello World"}
this.message = JSON.parse(result).message;
});
But I actually have to get it from _body:
this.service.getHello()
.then( result => {
this.message = JSON.parse(result._body).message;
console.log(this.message);//Hello World
});
Is it a RestEasy configuration thing, is there a way to change that?
Or
Should I consider that I will always have a field _body in my response with my data, and that's the default response structure?
For eventual consideration, here is my backend code:
HelloWorld Service:
#Path("/hello")
#Produces({ "application/json" })
#Consumes({ "application/json" })
public class HelloWorld {
public HelloWorld() {}
#GET
#Path("/world")
public Message getHello(){
return new Message("Hello World!!");
}
}
My RestEasy version is 3.1.1.Final running in Wildfly 10.1.0.Final
What you're getting back is the Response object from the Http request. This is what all Http operations will return. The easiest way to parse the JSON from that is to just call the json() method on it
this.service.getHello()
.then((res: Response) => {
let obj = res.json();
});
If you want the getHello to just return the object without having to parse it (on the calling client), then you can do it inside the getHello method by mapping it (using the Observable.map operation)
getHello() {
this.http.get(..)
.map((res: Response) => res.json())
.toPromise();
}
As peeskillet says above, you're getting back the entire Response from the request, and while sometimes you may want to examine the headers, perhaps to handle the different return conditions (retry or redirect on 4xx or 5xx responses for example), most of the time we assume a successful request and we just want the payload.
Angular2 encourages the use of Observables, so your service might look something like this:
getHello()
{
return this.http.get(http://localhost:8080/helloapp/rest/hello/world)
}
And your component may look something like this:
data: string;
ngOnInit() {
this.service
.getHello()
.map(response => response.json())
.subscribe (
data => {
this.data = data,
},
err => console.log('Error',err),
() => console.log('data',this.data)
);
}
You call the service, which is an http.get() and returns an Observable object, and we use .map to parse the response as JSON, which also returns an Observable, which we subscribe to.
Subscribe has three callback functions,
.subscribe(success, failure, complete)
In the example above on success we assign the payload - data - to this.data, if the subscribe fails, you log the error, and when it completes, we can do whatever we like, but in this case, we log this.data to the console - that's optional, but I log out the results while developing and then strip them out later.
I am working on sending JSON data from my HTTP server to my client. I have been successful in sending smaller sized JSON responses to the client, but once I have to wait and collect all the data before sending, my code does not function properly. I am using the .on('data', function (){}) method to collect the data and build it back up and the .on('end', function(){}) to try sending the data, but my code never enters either of these methods.
My code for sending the larger sized JSON data is below:
exports.sendJson = function (req, resp, data) {
resp.writeHead(200, "Valid EndPoints", { "Content-Type": "application/json" });
var payload = '';
resp.on('data', function(data){
payload += data;
})
.on('end', function(){
resp.write(JSON.stringify(payload));
});
resp.end();
};
My code that works fine for smaller sized JSON data is as follows:
exports.sendJson = function (req, resp, data) {
resp.writeHead(200, { "Content-Type": "application/json" });
if(data) {
resp.write(JSON.stringify(data));
}
resp.end();
};
Thanks in advance. I'm actually pretty happy I got this far.
A HTTP server response is a Writable; it does not emit data events.
If the thing you pass in to sendJson's data parameter is an object, you just do exactly what you're doing in the second example. There is no need to buffer anything. (If the thing you pass to sendJson is a stream, just pipe it to the response.)
(When parsing received JSON, you must buffer the data you get from a Readable -- the HTTP response on the client.)
I'm using the fetch-api for the first time and having trouble passing a non-stringified JSON objects to the server.
Basically I want to achieve the same behavior as this:
$.post(url, {"test": "test"}, function(response) {
console.log(response);
});
The fetch method is communicating with an web API which is unaccessable for me and expects a plain JSON object.
Normally I would just use FormData to pass data to the server, however the JSON will be transformed to a string [Object object]:
fetch(url, {
method: 'POST',
body: {"test": "test"}
})
.then(data => data.json())
.then(json => console.log(json))
.catch(e => console.error(e));
The body request seems to be empty when using $_POST (which is what the API is using), though gives the right value when using file_get_contents('php://input).
I though this had something to do with the wrong header given to the request. So I tried to add the header Ajax post uses: content-type:multipart/form-data;. However, this also did not get any value.
I was wondering if this was explicity intentional to not use plain JSON object to give as data, or that I'm simply missing something?
This does work, but is not allowed as it is a stringify version of the JSON object:
var formData = new FormData();
formData.append('data', JSON.stringify(data));
fetch(url, {
method: 'POST',
body: formData
})
.then(data => data.json())
.then(json => console.log(json))
.catch(e => console.error(e));
Let's say your data is inside a variable var data = { a: "some data", b: 123 }. If you want your code in PHP to access these fields this way:
$_POST["a"] == "some data";
$_POST["b"] == 123;
Then you need to send the data in the formData format this way:
var fdata = new FormData();
fdata.append('a', 'some data');
fdata.append('b', '123');
Now you can send that data and PHP will have access to separated fields a and b but notice b will be a string, not a number.
What if you want to send an array. Let's say { c: ['hello', 'world', '!'] }? You must follow PHP name conventions and add the same name multiple times:
var fdata = new FormData();
fdata.append('c[]', 'hello');
fdata.append('c[]', 'world');
fdata.append('c[]', '!');
After setting the form data instance, you can use it as the body of the request.
So firstly, I need to post to the POST-protocol, which is used by $_POST. I do this by adding a header of application/x-www-form-urlencoded (which is the protocol used by $_POST, as described in the docs) to the fetch post request:
fetch(url, {
headers: new Headers({'Content-Type': 'application/x-www-form-urlencoded'}), // Default header which $_POST listens to
...
Now the way $.post actually sends data is by creating a serialized string (eg: a%5Bone%5D=1) of the given object. To transform an object to a serialized string, you can use $.param:
fetch(url, {
headers: new Headers({'Content-Type': 'application/x-www-form-urlencoded'}), // Default header which $_POST listens to
method: 'POST',
body: $.param(data)
})
This will make you able to retreive data from $_POST like you would do with a simple $.post.
I am designing a used cars website using AngularJS and NodeJS/Express. The database is MySQL (so not quite a MEAN stack).
I am very familiar with Angular but this is the first time I have used Express (in the past I have gone for JAX-RS).
I have no problem whilst only sending one or two paramaters e.g.
app.get('/api/images/:vehicleId', function (request, response) {
images.getThumbnailImage(request, response, connection, request.params.vehicleId);
});
but I am unsure how to move forward with multiple parameters, some of which are optional.
The client is built using TypeScript. The form data is collected by way of a TypeScript object, but I am not sure what the best practice is for sending multiple parameters.
The options I have thought of are:
1). Send the object and then use that to build a query:
return this.$http({
method: 'POST',
url: this.API_ADDRESS + 'vehicles/',
data: vehicleSearchModel,
headers: {
'Content-Type': 'application/json'
}
}).then((response: any) => {
return response.data;
});
and retrieve it from the body using body-parser i.e.
request.body.data (or something similar)
or
2). send multiple params in the url i.e.
app.get('/api/vehicles/:make/:model/:bodyStyle/:fuelType/:transmission/:minPrice/:maxPrice/:minYear/:maxYear/:counties', function (request, response) {
//Do something with request.params!!!
});
Please advise.
First, you should make the http post request as following.
var data = {
make : make,
model : model,
fuelType : fueltype,
....
}
return this.$http({
method: 'POST',
url: this.API_ADDRESS + 'vehicles/',
data: vehicleSearchModel,
headers: {
'Content-Type': 'application/json'
}
}).then((response: any) => {
return response.data;
});
And then, you can receive the multiple parameters as following.
app.post('/api/vehicles/', function(req, res){
var make = req.body.make;
var model= req.body.model;
var bodyStyle= req.body.bodyStyle;
var fuelType= req.body.fuelType;
var transmission= req.body.transmission;
.....
});