Not able to access Object values returned from a web service in React - javascript

Here are whats returned in response when hitting the service:
{
"2019-04-20":{
"fare":0,
"IsPricePos":false
},
"2019-04-19":{
"fare":0,
"IsPricePos":false
},
"2019-03-27":{
"fare":45,
"IsPricePos":true
},
"2019-03-26":{
"fare":9,
"IsPricePos":true
},
"2019-03-25":{
"fare":23,
"IsPricePos":true
}
}
Using the below code for hitting web service and getting a response:
fetch("/somepath/somefurtherpath/" + src + "/" + dst)
.then(response => response.json())
.then(result => Object.assign(newObj, result));
I am using fetch API as shown.
1) JSON.stringify(newObj) returns {} i.e. empty object string.
2) Not able to do JSON.parse(newObj) as it says its already an object.
3) Object.keys(newObj) returns an empty list.
The console.log(newObj) gives below (opening the object printed in console):
{}
2019-03-21:
IsPricePos: true
fare: 45
__proto__: Object
2019-03-22: {fare: 45, IsPricePos: true}
2019-03-23: {fare: 45, IsPricePos: true}
2019-03-24: {fare: 23, IsPricePos: true}
I need to access data in JSON and do operations on it. e.g. keys and its values.
I need to access values of fare or IsPricePos for any given dates as keys.
I tried accessing the values as newObj."2019-03-25".fare, but did not work too.
What is the best way to do this? Does React have any specific issue with this type of situation?
I tried hardcoding an object and accessing values using JavaScript, it works well. But this situation is an issue.
Please help. Thank you.

Related

Is there a way to configure the Firestore timestamp outputs?

I'm using Firestore to keep timestamps such as this log output:
{
my_timestamp: Timestamp { seconds: 1676783325, nanoseconds: 209000000 },
product_name: 'Android'
}
I'm reading the values in my web app like this:
...
const result = []
productDocs.forEach((productDoc: DocumentData) => {
result.push({ id: productDoc.id, ...productDoc.data() })
})
return result
...
But I get an error:
Server Error
Error: Error serializing `.productDoc[0].my_timestamp` returned from `getStaticProps` in "/[pid]".
Reason: `object` ("[object Object]") cannot be serialized as JSON. Please only return JSON serializable data types.
It seems to me that the Timestamp object is not easily accepted as part of the object. My solution is to iterate through each Object.entries(productDoc).forEach(productData)... and reformat the Timestamp object and then push on an array.
This seems like a manual way to go about this so I'd like to make sure I'm parsing the timestamp object properly and I'm not missing some way where I can just read the whole result from Firebase as an object with doing nothing to the timestamp.
It seems How do I convert a Firestore date/Timestamp to a JS Date()? is the only way where I have to take the object apart and convert the values.
I didn't see a way to do this on https://firebase.google.com/docs/reference/js/firestore_.timestamp other than just converting the Firebase object.
Using the DocumentSnapshot type should solve your problem:
const result = []
productDocs.forEach((productDoc: DocumentSnapshot) => {
result.push({ id: productDoc.id, ...productDoc.data() })
}
A DocumentSnapshot contains data read from a document in your Firestore database while a DocumentData is to be used with the setDoc() method.

JSON object from Angular http not deserializing properly

First here are my operating versions: node v12.13.1 | npm 6.12.1
I am having some issues understanding why this isn't de-serializing properly. I am receiving the following back from my rest service.
{ "numbers":[],
"batches":[
{ "id":"AB3E809","status":"1"},
{ "id":"EEF32A9","status":"0"}] }
These are the TypeScript interfaces I am using when trying to type the data.
interface NumJson {
status: string,
num: string
}
interface BatchJson {
id: string,
status: string
}
interface Status {
numbers: NumJson[],
batches: BatchJson[];
}
When making these calls from my Angular service, it doesn't seem to recognize or access the data properly.
this.http.get<any>(url).subscribe({
next: (data: Status) => {
console.log(data); // same as JSON above
console.log(data.numbers); // undefined
console.log(data.batches); // undefined
}
this.http.get<any>(url).subscribe({
next: (data: any) => {
console.log(data); // same as JSON above
console.log(data.numbers); // undefined
console.log(data.batches); // undefined
}
Any insights on this would be great as this is the only subscribe that is having issues.
I figured out the issue after some thought provoking examples from 'Kurt Hamilton'. My issue was with how the rest service was returning my data.
The correctly formatted data should look like this in the console:
My outputs were displaying strings; which made me question why my data was a string verse an object in the console. (A good note to take away from this issue)
After inspecting the rest service, I realized that it was doing a double serialization. Once I corrected that, the data output looked and acted correctly.

How to limit the amount of data returned from a JSON file using fetch?

I have this fetch statement that returns 19 building names, but I only want 10; the following is what I attempted, but I still get 19 building names.
fetchBuildings(energyProgramId) {
fetch(`http://localhost:1001/api/energyprograms/${energyProgramId}/buildings/?results=10`)
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
buildings: json,
})
});
}
Is there something extra I need to add?
Here is an example:
1.fetch('http://jsonplaceholder.typicode.com/posts/')
The above URL gives array of objects with 100 elements because it originally is an array of 100 elements.
2.fetch('http://jsonplaceholder.typicode.com/posts/?_limit=10')
This URL gives array of objects with 10 elements.
Notice the difference?
I only did this : ?_limit=10 ----> Add any number in place of 10 and hopefully you will get desired results.
As the other answer already points out the best/most normal solution would be to change on the backend how the API returns data. Typically REST API's support query parameters such as limit and start or page and resultsPerPage.
If this is not available - e.g. when you're fetching an external resource - an alternative which is often supported by static file servers and sometimes by API's is the Range header which allows you to retrieve only a specific byte range of the resource (do note, in the case that an API supports this it will still load the entire resource on the server, but it will not transmit the entire resource). An example with fetch would look like
fetch('', { headers: { range: 'bytes=0-1000'} })
When doing this on XML or JSON resources it can be somewhat difficult to work with, but with for example CSV files it's ideal.
No different from fetch to XHR or axios or anything else. actually, no different from react or angular or vue or anything else.
This is an API that backend developers wrote it and it is based on REST API, so when you call it as GET or POST and anything else you just fetch the JSON that the backend developers designed it. BUT
There is a new technology that name is GraphQL. you can call API and then you just fetch the JSON what you want. Also, it must be implemented in backend but it is possible.
It's not closely bound up with React. If you need less data you must reduce data before set the state.
const reducedBuildings = [];
fetch(`http://localhost:1001/api/energyprograms/${energyProgramId}/buildings/?results=10`)
.then(res => res.json())
.then(json => {
json.forEach(building => {
if (reducedBuildings.length < 10) {
reducedBuildings.push(building);
}
});
this.setState({
isLoaded: true,
buildings: reducedBuildings,
})
});

Firebase js library retrieves empty data from non empty database

steps to reproduce:
Initialize your firebase db to:
{
"restaurants" : [ {
"address" : "via Rettifilo, 34 Castelguidone CH Italy",
"title" : "Dama & Dama"
}, {
"address" : "Corso Umberto I, 3 Castelguidone CH Italy",
"title" : "Bar sabatino"
} ]
}
Check your read/write firebase persmission rules to be
{
"rules": {
".read": true,
".write": true
}
}
Execute this js code:
firebase.inizializeApp(yourJsonConfig)
\*code*\
firebase.database().ref().once('value').then(function(snapshot){
console.log(snapshot.val()); \\ this will print Array(0)
})
Expected behaviour: console logs "{'restaurants' ........}"
Actual behaviour: console logs "Array(0)" i.e. NO DATA!
I use firebase js library (version 4.13.1). Where am I wrong?
You need use val() method to return your data.
firebase.database().ref().once('value').then(function(snapshot){
console.log(snapshot.val());
})
Edit: Then your problem exist in another piece of code what you did not show.
Check this example: http://jsfiddle.net/zgfr91yd/
In console log:
And see my data:
You need a unique key for parent of each restaurant. You can use 'push' function in Firebase for that.
The snapshot argument that's being passed to your callback is an object of type DataSnapshot. You shouldn't assume that the JSON formatting string of a DataSnapshot contains just the data from that location in the database. As you can see from the API docs, there are a lot of methods functionality in a DataSnapshot.
What you what to do is call val() on that snapshot in order to extract a JavaScript value from it. Read the API docs to further understand what that object may contain.

Parse error code 121

I am trying to save a value on a 'collection' called 'orders'. But when i click 'save', it gives me an error code 121.
I have already checked my key-value parameters, but i can't find a $ or a . to make it give me this error...
Here is my code (the variable names are in portuguese, but only that)
var objRevenda = Parse.Object.extend("resellers"),
objPedido = Parse.Object.extend("orders"),
query = new Parse.Query(objRevenda),
idRevenda = $scope.revenda.id;
query.get(idRevenda, {
success: function(revenda) {
var valores = {
status: 'aberto',
client: $rootScope.usuarioAtual,
reseller: revenda,
payment_method: metodo_pgto,
items: $scope.itens,
total: $scope.totalPedido
};
var pedido = new objPedido();
pedido.save(valores, {
success: function(pedido) {
console.log('Sucesso');
},
error: function(pedido, error) {
console.error('Ops... ', error);
}
});
},
error: function(revenda, error) {
console.log(error);
}
});
Can someone help me find the error?
Btw: I am using AngularJS and Ionic Framework.
Thanks in advance.
If you are using a JSON object (sending it to Parse via AngularJS), it will have a $$hashKey, wich Angular uses to make ng-repeats and all, having unique identifiers. If you use JSON.Parse(object), Angular creates the $$hashKey, altough, if you use angular.toJson(object), the hash key should be gone. Make sure that before sending to Parse, you do a console.log(json-object), to make sure the hash key is really gone. If not, i think you should remove it by doing a conditional operation. I removed the hash key and now it works like a charm ;)
I figured out that if you are using angular (maybe other frameworks as well) that an identical embedded key/value pair on multiple levels will result in a $$hashKey key being created and will cause this error.
Maker sure that none of your objects contain something like the following:
{
id: 65ftvjbh,
user: {
id: 65ftvjbh,
name: John Doe
}

Categories