'how to parsing web socket response (JSON) in flutter
I have a task, I want to take the data through the web socket, and display them on the screen of the application. But I did not even find a normal example to do so. I will be grateful if someone helps to do it, or someone sets an example. I have the socket web address:
wss: //ws-sandbox.coinapi.io/v1/
I also have a body that I will send to the socket to return the data:
{ "type": "hello", "apikey": "C4F12EA7-D405-4619-99FD-62F4B00A8111", "heartbeat": false, "subscribe_data_type": ["exrate"], "subscribe_filter_asset_id": ["BTC / USD"] }
Here's what comes back in the web socket:
{
"time": "2022-04-28T16: 45: 31.0000000Z",
"asset_id_base": "BTC",
"asset_id_quote": "USD",
"rate": 39693.575,
"type": "exrate"
}
I want to display "rate" data on the screen. I will be grateful for your help)
My code
import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/io.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
WebSocketChannel channel = IOWebSocketChannel.connect("wss://ws-sandbox.coinapi.io/v1/");
@override
MyHomePageState createState() {
return MyHomePageState();
}
}
class MyHomePageState extends State<MyHomePage> {
TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Web Socket"),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Form(
child: TextFormField(
decoration: InputDecoration(labelText: "Send any message to the server"),
controller: _controller,
),
),
StreamBuilder(
stream: widget.channel.stream,
builder: (context, snapshot) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Text(snapshot.hasData ? '${snapshot.data}' : ''),
);
},
)
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.send),
onPressed: sendData,
),
);
}
void sendData() {
if (_controller.text.isNotEmpty) {
widget.channel.sink.add(_controller.text);
}
}
@override
void dispose() {
widget.channel.sink.close();
super.dispose();
}
}
Solution 1:[1]
In this case you do not want to display the entire json body. So instead of using snapshot.data you need to parse it first.
snapshot.data has a dynamic type so I do not know what kind of data you are working with but if you somehow parse it to a Map<String, dynamic> you can just do data['rate'].
When using the regular http library you can parse a http.Response like this:
jsonDecode(response.body).cast<Map<String, dynamic>>();
If you tell me the type of snapshot.data I might be able to give you more information.
Edit: I just tried your code and as suspected you are getting a String that we can parse with jsonDecode:
jsonDecode(snapshot.data)["rate"]
If we apply this to your problem this should be the solution:
Your Widget should look like this:
Text(getExtractedRate(snapshot))
The getExtractedRate method should looke like this:
String getExtractedRate(AsyncSnapshot<dynamic> snapshot) {
return snapshot.hasData ? '${jsonDecode(snapshot.data)["rate"]}' : '';
}
Keep in mind that I am using the dynamic type to avoid typing conflicts. jsonDecode requires a String while snapshot.data is Object?. In your production code you also might want to check if the key rate is present before accessing it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
