Accessing JSON in state - ReactNative - json

For my ReactNative proejct: I'm currently trying to access a weather API and retrieve a .json file, store it in my state variable, and then access relevant objects within the .json file (ex: the current temperature, etc).
I'm able to access the entire .json file through my component's State. However, when I try to access objects (ex: current temperature), I get this error. I'm pretty sure I'm using the correct JSON key names to access it, so not sure what's wrong.
TypeError: Cannot read property 'temp_c' of undefined
Here's my code:
class App extends Component {
state = {weatherResponse: []}; // the state of the App component
componentWillMount() {
axios.get('http://api.apixu.com/v1/current.json?key=KEY&q=Paris')
.then(
function(response) {
//console.log(response.data);
this.setState({weatherResponse: response.data}); //here, I store the json file into the state.
}.bind(this)
);
}
render() {
console.log(this.state.weatherResponse); //this works, no problem.
console.log(this.state.weatherResponse.current.temp_c); //this returns the error below.
Here's the JSON file:
{
"location": {
"name": "Paris",
"region": "Ile-de-France",
"country": "France",
},
"current": {
"last_updated_epoch": 1517616126,
"last_updated": "2018-02-03 01:02",
"temp_c": 2,
"temp_f": 35.6,
"is_day": 0,
"cloud": 75
}
}
Can you please help? Thanks!

In your initial render this.state.weatherResponse is empty, it only gets the data once your api request is completed and the state is updated. You should check whether weatherResponse contains the value before trying to access it.

Related

Trying to get some position of JSON using Observables

Sorry for the question, but I'm newer in Typescript and Ionic and Im a bit confused about how should I proceed.
I have a JSON file with 150 entries based on an interface I'm declared quite simple:
export interface ReverseWords {
id: number;
todo: string;
solution: string;}
On the other hand, I have a service which reads the json file and returns an Observable of this type (ReverseWords)
getReverseWords() {
return this.http.get<ReverseWords>('/assets/data/reves.json');}
On .ts file, I call the service and I have all the content of the JSON file. What I want to do (and Im not able to do) is get only one entry based on a random position.
On .ts file:
reverseWords: Observable<ReverseWords>; // All the JSON content
reverseWordsSelected: Observable<ReverseWords>; // I would like to get one entry here
On ngOnInit():
this.reverseWords = this.dataservice.getReverseWords();
Everything is fine until here, I've got all the content and I can log it in console. I'm using Observables so I need to subscribe to it to get the information. And I use rxjs/operators pipe and filter to try it, but nothing is showing in the chrome developer console (not even an error).
const reverseWordSelectedByPosition = this.reverseWords.pipe(filter(reverseWord => reverseWord.id === randomPosition));
reverseWordSelectedByPosition.subscribe(console.log);
Could anybody help me and tell me what I'm doing wrong?
Other thing I've tested is to do the following in the service:
getReverseWords() {
return this.http.get<ReverseWords[]>('/assets/data/reves.json');}
And then in the .ts file:
reverseWords: Observable<ReverseWords[]>;
But I have the same problem.
Finally, the most weird thing is that if I write in the .ts file this simple test:
const test = from([
{
id: 1,
todo: 'chapter',
solution: 'r-e-t-p-a-h-c'
},
{
id: 2,
todo: 'claustrofobia',
solution: 'a-i-b-o-f-o-r-t-s-u-a-l-c'
},
{
id: 3,
todo: 'keyboard',
solution: 'd-r-a-o-b-y-e-k'
}
]);
Everything is fine and I can see on the log only 1 entry if I choose 2, for example.
Any help or advice??
Thanks and sorry for the long approach!!
As TotallyNewb suggested, I show an example of the JSON file, with only 3 entries:
[
{
"id": 1,
"todo": "chapter",
"solution": "r-e-t-p-a-h-c"
},
{
"id": 2,
"todo": "claustrofobia",
"solution": "a-i-b-o-f-o-r-t-s-u-a-l-c"
},
{
"id": 3,
"todo": "keyboard",
"solution": "d-r-a-o-b-y-e-k"
}
]
Since you are getting the whole array you can use map
this.reverseWords.pipe(
map((items) => items[Math.floor(Math.random() * items.length)]), // Creates a random index based on the array length
)
.subscribe(console.info);
If you want to pass the result to reverseWordsSelected, you can change it to a Subject and pass the value to it from the subscription of reverseWords with .next().
You can check out this stackblitz for a working example

Design Automation LogTrace onProgress cannot match arguments in custom call

I am trying to export a .sat file to one in .stp format. I've had trouble doing the export directly to a bucket (from .ipt to .stp no problem but it doesn't work from .sat to .stp).
Finally, I have tried using LogTrace with custom data to send the file data through a string (step format has string content and it's created correctly). Unfortunately, I can't make work the callback !ACESAPI:acesHttpOperation with the custom data (it does work by default).
This is my workitem call
{
"activityId": "DNhofWmrTzDm5Cdj3ISk0yvVA0IOBEja.InventorActivity16+3",
"arguments": {
"InventorDoc": {
"url": "https://developer.api.autodesk.com/oss/v2/signedresources/xxxxxxxx-aa45-43fa-8c0e-e594a3f671cc?region=US"
},
"InventorParams": {
"url": "data:application/json,{\"height\":\"16 in\", \"width\":\"10 in\"}"
},
"onProgress": {
"verb": "post",
"url": "https://xxxxxxx"
}
}
And this is a part of the log response
I think there is a problem with the API call from !ACESAPI:acesHttpOperation.
I follow same instructions from
callback documentation
Thanks in advance

Best Schema for a Data List in JSON for RestFul API to use in Angular

I've been wondering for some days what kind of scheme would be more appropriate to use a data list in json in a web application.
I'm developing a REST Web Application, and im using Angular for front end, i should order, filter and print these data list also in xml ...
For you what scheme is better and why?
1) {
"datas": [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
]
}
2) {
"datas": [{
"data": { "first":"","second":""},
"data": { "first":"","second":""},
"data": { "first":"","second":""}
}]
}
3) [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
]
Thanks so much.
The first and third notations are quite similar because the third notation is included in your first.
So the question is "Should I return my datas as an array or should I return an object with a property that contain the array ?
It will depend on either you want to have more information alongside your datas or not.
For exemple, if your API might return an error, you will want to manage it from the front end.
In case of error, the JSON will looks like this :
{
"datas": null,
"error": "An error occured because of some reasons..."
}
At the opposite, if everything goes well and your API actually return the results, it will looks like this :
{
"datas": [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
],
"error": null
}
Then your front end can use the error property to manage errors sent from the API.
var result = getDatas(); // Load datas from the API
if(result.error){
// Handle the error, display a message to the user, ...
} else {
doSomething(result.datas); // Use your datas
}
If you don't need to have extra properties like error then you can stick with the third schema.
The second notation is invalid. The datas array will contain only one object which will have one property named data. In this case data is a property that is defined multiple times so the object in the array will contain only the last occurence:
var result = {
"datas": [{
"data": { "first":"a","second":"b"},
"data": { "first":"c","second":"d"},
"data": { "first":"e","second":"f"}
}]
}
console.log("Content of result.datas[0].data : ")
console.log(result.datas[0].data)
Obviously the first option would be easy to use. Once you will access datas it'll give you an array. Any operation (filter, sort, print) on that array will be easy in comparison to anything else. Everywhere you just need to pass datas not datas.data.

Reading from a non-static JSON file in an Angular4 app

I have a basic Angular web app which reads from a JSON file located on the same server as the app and parses through the JSON file in order to set certain values on objects which drive certain behavior in my app (applies css classes, etc.)
I am not able to find online and/or figure out myself how to set up the controller to read from the JSON file in a way that allows the file to be changed and Angular to dynamically reload the file once it has been changed without reloading the entire page. The JSON file is local on the server where the app is deployed, and I wanted to avoid standing up a web service just to serve a file that already exists on the same server the app is deployed.
Here is what I am doing now:
ngOnInit(): void {
// Make the HTTP request:
this.http.get('../assets/applicationLogs.json').subscribe(data => {
// Read the result field from the JSON response.
this.node_a_status= data.nodes[0].status;
this.node_b_status= data.nodes[1].status;
this.node_c_status= data.nodes[2].status;
});
}
And here is a what my JSON file looks like:
{
"nodes":[
{ "node":"Node A", "status":"processing", "errors":null },
{ "node":"Node B", "status":"processing", "errors":null },
{ "node":"Node C", "status":"inactive", "errors":null }
]
}
First, I know I will probably need to move this get logic out of ngOnInit(), but I am a little lost on how I should go about achieving the desired behavior I have described with typescript.
You're using an http request method on the file so "Poll it"... same way you would any other http JSON service. Here's a ready made poller for you to import: https://www.npmjs.com/package/rx-polling
Best thing you can do is create a service out of it and call it in ngOnInit method and use the response the same way you've shown.
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/dom/ajax';
import 'rxjs/add/operator/map';
import polling from 'rx-polling';
// Example of an Observable which requests some JSON data
const request$ = Observable.ajax({
url: '../assets/applicationLogs.json',
crossDomain: true
}).map(response => response.response || [])
.map(response => response.slice(0, 10)); // Take only first 10 comments
polling(request$, { interval: 5000 }).subscribe((comments) => {
console.log(comments);
}, (error) => {
// The Observable will throw if it's not able to recover after N attempts
// By default it will attempts 9 times with exponential delay between each other.
console.error(error);
});

node.js read file in, parse to JSON and output

I'm very new to anything much code related, but I'm on a slow and sometimes painful learning curve.
I have a file containing some json which I read into node.js parse and push to a web socket. The script works fine, but I only ever get one json object returned.
devices.json: (Complete file) Not every element has the same data contents, and there is any number of element objects within a data source.
{
"element":"SENS01",
"data":{
"type":"SEN",
"descr":"T100"
},
"element":"SENS02",
"data":{
"type":"SEN",
"descr":"T088",
"uid":"X1A1AA",
"check_on":"2014/06/29"
},
"element":"SENS03",
"data":{
"type":"SEN",
"descr":"T000:",
"uid":"X1A1AB",
"check_on":"2014/06/29"
},
"element":"LED1",
"data":{
"type":"LED",
"state":"0"
}
}
The code which does the stuff is;
server.js:
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs');
// creating the server ( localhost:8000 )
app.listen(8000);
// Server started - load page.
function handler(req, res) {
fs.readFile('/var/www/html/dashboard.html', function (err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading web page');
}
res.writeHead(200);
res.end(data);
});
}
// creating a new websocket.
io.sockets.on('connection', function (socket) {
console.log();
// 1st READ of json state file.
fs.readFile('devices.json', 'utf8', function (err, data) {
if (err) throw err;
// Parse/check its valid json.
var dump = JSON.parse(data);
socket.volatile.emit('MAP.room1', dump);
});
});
When I connect to the socket the following is sent (as logged from the server console)
debug - websocket writing 5:::{"name":"MAP.room1","args":[{"element":"LED1","data":{"type":"LED","state":"0"}}]}
I never get any of the other objects, only this one. I've had a look round the net about how to iterate over objects, but it was all largely meaningless to me :(
What I am trying to achieve is when you connect to the web socket every object from the devices.json file is pushed out 1 object at a time. So once this is working I would expect to see;
debug - websocket writing 5:::{"name":"MAP.room1","args":[{"element":"LED1","data":{"type":"LED","state":"0"}}]}
debug - websocket writing 5:::{"name":"MAP.room1","args":[{"element":"SENS03","data":{"type":"SEN","descr":"T000:","uid":"X1A1AB","check_on":"2014/06/29"}}]} etc...
If I put a console.log(data) line in my server.js then I see the entire file as expected. Its only once its been parsed am I left with the 1 entry.
Can anyone please explain what's going on, and how I can best overcome this. It needs to be in a really simple way ideally using my own code/dataset as examples so I can understand 'what this means for me' A lot of the web examples and stuff I read tend to use different examples which just confuses me. I know the basics of declaring variables etc, and have an extremely limited experience with Ruby with a simple script to parse some push data received from an API but that's about it.
If you need any more context etc then please let me know, otherwise any help gratefully received.
I think your problem is that you're using the same keys in your JSON. When the parser reads in that JSON, it continuously overwrites previous values of element and data and since those are the only unique key names, those are the only two values you see.
If you modified your JSON so that the same key names are not used on the same "level," then you would see all of the data you are expecting. Here's an example that makes it easy to iterate through each element:
[
{
"element":"SENS01",
"data":{
"type":"SEN",
"descr":"T100"
}
},
{
"element":"SENS02",
"data":{
"type":"SEN",
"descr":"T088",
"uid":"X1A1AA",
"check_on":"2014/06/29"
}
},
{
"element":"SENS03",
"data":{
"type":"SEN",
"descr":"T000:",
"uid":"X1A1AB",
"check_on":"2014/06/29"
}
},
{
"element":"LED1",
"data":{
"type":"LED",
"state":"0"
}
}
]
Or if you can guarantee that the element values are always unique, then perhaps you could also do this:
{
"SENS01":{
"type":"SEN",
"descr":"T100"
},
"SENS02":{
"type":"SEN",
"descr":"T088",
"uid":"X1A1AA",
"check_on":"2014/06/29"
},
"SENS03":{
"type":"SEN",
"descr":"T000:",
"uid":"X1A1AB",
"check_on":"2014/06/29"
},
"LED1":{
"type":"LED",
"state":"0"
}
}
Ok so I found out my data was actually JS objects represented as below in a flat format with every object seperated with a linefeed.
{"SENS01":{"type":"SEN","descr":"T100"}
{"element":"LED1","data":{"type":"LED","state":"0"}
Using linereader (from npm) I was able to read the file in by doing;
lineReader.eachLine('simple.txt', function(line) {
var dump = JSON.parse(line);
socket.emit('MAP.room1', dump);
});
That then output the required data from the web socket.