I'm new to Flutter and Dart and I have been struggling with saving values in shared preferences to use when my app is restarted. I have successfully stored variables, but I also need object lists to be stored. I know that since shared preferences only accept String lists, I need to convert my object list into a JSON array and when the app is restarted, retrieve this list and convert it to an object list again.
I was able to encode the object list to JSON and I got something like this:
[{name: Rent, amount: 250}, {name: Insurance, amount: 105}]
I achieved this with the following function:
void SaveLists(key, value) async { //where value is a List<Object>
final prefs = await SharedPreferences.getInstance();
List<dynamic> json_list = (value.map((i) => i.toJson())).toList();
prefs.setStringList(key, json_list); //this line causes the error
print('$json_list');
}
The List json_list contains the JSON array that is shown above. However when I try to store it in the shared preferences with prefs.setStringList(key, json_list); I get the following error:
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<String>'
Now, let's say that I somehow store it successfully in shared preferences, how do I convert the JSON array back to a List when called with prefs.getString('key')?
In case you need to see the class, here it is:
import 'dart:convert';
class Random_expenses {
String name;
double amount;
Random_expenses({this.name, this.amount});
Random_expenses.fromJson(Map<String, dynamic> json)
: this.name = json['name'],
this.amount = json['amount'];
Map<String, dynamic> toJson() =>
{'name': this.name, 'amount': this.amount};
}
You can copy paste run full code below
You can save List<RandomExpenses> as a json string with randomExpensesToJson(value)
You can get List<RandomExpenses> with randomExpensesFromJson(keyString)
code snippet
List<RandomExpenses> randomExpensesFromJson(String str) =>
List<RandomExpenses>.from(
json.decode(str).map((x) => RandomExpenses.fromJson(x)));
String randomExpensesToJson(List<RandomExpenses> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
...
void saveData(String key, List<RandomExpenses> value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, randomExpensesToJson(value));
}
Future<List<RandomExpenses>> getData(String key) async {
final prefs = await SharedPreferences.getInstance();
String keyString = prefs.getString(key);
return Future.value(randomExpensesFromJson(keyString));
}
...
await saveData("key", randomExpensesList);
List<RandomExpenses> list = await getData("key");
print('${list[0].name} ${list[0].amount}');
print('${list[1].name} ${list[1].amount}');
output
I/flutter (24879): Rent 250
I/flutter (24879): Insurance 105
full code
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
List<RandomExpenses> randomExpensesFromJson(String str) =>
List<RandomExpenses>.from(
json.decode(str).map((x) => RandomExpenses.fromJson(x)));
String randomExpensesToJson(List<RandomExpenses> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class RandomExpenses {
String name;
int amount;
RandomExpenses({
this.name,
this.amount,
});
factory RandomExpenses.fromJson(Map<String, dynamic> json) => RandomExpenses(
name: json["name"],
amount: json["amount"],
);
Map<String, dynamic> toJson() => {
"name": name,
"amount": amount,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
List<RandomExpenses> randomExpensesList = [
RandomExpenses(name: "Rent", amount: 250),
RandomExpenses(name: "Insurance", amount: 105)
];
void saveData(String key, List<RandomExpenses> value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, randomExpensesToJson(value));
}
Future<List<RandomExpenses>> getData(String key) async {
final prefs = await SharedPreferences.getInstance();
String keyString = prefs.getString(key);
return Future.value(randomExpensesFromJson(keyString));
}
void _incrementCounter() async {
await saveData("key", randomExpensesList);
List<RandomExpenses> list = await getData("key");
print('${list[0].name} ${list[0].amount}');
print('${list[1].name} ${list[1].amount}');
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Related
I am new to flutter and trying to fetch API data into a list. My goal is to later input that information into a ListView.
I am familiar with doing api calls but now I'm triying to get information from a json array. Previously I made a model class to retrieve the objects I need to continue with my process, but I've reached a dead end since I can't seem to figure out how to extract the objects from an array properly.
I am using multiple files. "API Services", "readData Model", and the actual screen where the data will be shown.
Everything else is fine, it's just that I am unable to actually save the data to a list.
First I will show you how my code is set up and the JSON response data I am trying to save:
JSON Response Body:
The example I am showing only has one chunk of image data, but we need an array for it since it should be displaying every chunk in a list.
{"status":200,
"content":[{"image_id":"151",
"image_url":"https:\\\/imageurl.jpg",
"returned_value":"14.0",
"alarm":"false",
"account":"test#email.com",
"create_at":"2020-11-17 07:13:42",
"location":"NY"
}]
}
API POST function:
Future<ReadResponseModel> readData(
ReadRequestModel requestData) async {
final response = await http.post("$url/read",
body: requestData.toJson() ,
headers: {
"Client-Service": "frontend-client",
"Auth-Key": "simplerestapi",
"Content-Type":"application/x-www-form-urlencoded",
"Authorization": token,
"User-ID": userId,
});
print(response.body);
if (response.statusCode == 200 || response.statusCode == 400) {
dynamic resBody = json.decode(response.body);
return ReadResponseModel.fromJson(resBody);
} else {
throw Exception('Failed to load data!');
}
}
readResponseModel Class:
I have tried two methods to process this information but have failed at both of them.
This is Method 1:
This one will give me the following error: [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
Originally set as final String for all values, but since I was getting this error I've been trying to make sure each one is the correct type (ex. retVal as int or alarm as bool). Still no luck so far.
class ReadResponseModel {
final dynamic imageID;
final dynamic imgUrl;
final dynamic retVal;
final bool alarm;
final dynamic account;
final dynamic createAt;
final dynamic location;
ReadResponseModel({this.imageID, this.imgUrl, this.retVal, this.alarm,
this.account, this.createAt, this.location,});
factory ReadResponseModel.fromJson(Map<String , dynamic> json) {
return ReadResponseModel(
imageID: json['content']['image_id'] as String ,
imgUrl: json['content']['image_url'] as String ,
retVal: json['content']["returned_value"] as String,
alarm: json['content']['alarm'] as bool ,
account: json['content']['account'] as String,
createAt: json['content']['create_at'] as String,
location: json['content']['location'] as String,
);
}
}
Method 2:
This one will give me the following error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type '(dynamic) => Content' is not a subtype of type '(dynamic) => String' of 'f' -- I dont even know where that f came from.
class ReadResponseModel {
List<String> content;
ReadResponseModel({this.content});
factory ReadResponseModel.fromJson(Map<String, dynamic> json) {
return ReadResponseModel(
content: json['content'] != null
? json['content']
.map<String>((json) => Content.fromJson(json))
.toList()
: null,
);
}
}
class Content {
final String imageID;
final String imgUrl;
final String retVal;
final String alarm;
final String account;
final String createAt;
final String location;
final String error;
Content({this.imageID,
this.imgUrl,
this.retVal,
this.alarm,
this.account,
this.createAt,
this.location,
this.error});
factory Content.fromJson(Map<String, dynamic> json) =>
Content(
imageID: json['image_id'],
imgUrl: json['s3_url'],
retVal: json['predict'],
alarm: json['alarm'],
account: json['account'],
createAt: json['create_at'],
location: json['location'],
);
}
The following code is just what I'm doing to connect all this to my widget:
APIService readService = new APIService();
readRequestModel.companyID = "123";
readService.readData(readRequestModel).then((value) async {
if (value != null) {
setState(() {
isApiCallProcess = false;
});
///Trying to call the fetched data and show it in the console:
print("Account: ${value.account}");
print("Returned Value: ${value.retVal}");
print("Image ID: ${value.imgUrl}");
}
I'm not entirely sure why I am getting these errors, and for method 2 I don't even know where that "f" came from. If anyone could shed some light on the subject it would be greatly appreciated.
You can copy paste run full code below
Step 1: Use List<Content> content; not List<String>
Step 2: Use List<Content>.from(json["content"].map((x) => Content.fromJson(x)))
Step 3: In sample JSON's image_url not equal model's s3_url, you need to modify to correct one
code snippet
class ReadResponseModel {
List<Content> content;
ReadResponseModel({this.content});
factory ReadResponseModel.fromJson(Map<String, dynamic> json) {
return ReadResponseModel(
content: json['content'] != null
? List<Content>.from(json["content"].map((x) => Content.fromJson(x)))
: null,
);
}
}
...
dynamic resBody = json.decode(jsonString);
ReadResponseModel model = ReadResponseModel.fromJson(resBody);
print(model.content[0].account);
output
I/flutter ( 4426): test#email.com
full code
import 'package:flutter/material.dart';
import 'dart:convert';
class ReadResponseModel {
List<Content> content;
ReadResponseModel({this.content});
factory ReadResponseModel.fromJson(Map<String, dynamic> json) {
return ReadResponseModel(
content: json['content'] != null
? List<Content>.from(json["content"].map((x) => Content.fromJson(x)))
: null,
);
}
}
class Content {
final String imageID;
final String imgUrl;
final String retVal;
final String alarm;
final String account;
final String createAt;
final String location;
final String error;
Content(
{this.imageID,
this.imgUrl,
this.retVal,
this.alarm,
this.account,
this.createAt,
this.location,
this.error});
factory Content.fromJson(Map<String, dynamic> json) => Content(
imageID: json['image_id'],
imgUrl: json['s3_url'],
retVal: json['predict'],
alarm: json['alarm'],
account: json['account'],
createAt: json['create_at'],
location: json['location'],
);
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
String jsonString = '''
{"status":200,
"content":[{"image_id":"151",
"image_url":"https:\\\/imageurl.jpg",
"returned_value":"14.0",
"alarm":"false",
"account":"test#email.com",
"create_at":"2020-11-17 07:13:42",
"location":"NY"
}]
}
''';
dynamic resBody = json.decode(jsonString);
ReadResponseModel model = ReadResponseModel.fromJson(resBody);
print(model.content[0].account);
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
From the above mentioned code I have created a sample example for you, basically you are messing up with the mode class.Take a look at the example below.
Json you provided:
{"status":200,
"content":[{"image_id":"151",
"image_url":"https:\\\/imageurl.jpg",
"returned_value":"14.0",
"alarm":"false",
"account":"test#email.com",
"create_at":"2020-11-17 07:13:42",
"location":"NY"
}]
}
Based on the json the model class below :
// To parse this JSON data, do
//
// final readResponseModel = readResponseModelFromJson(jsonString);
import 'dart:convert';
ReadResponseModel readResponseModelFromJson(String str) => ReadResponseModel.fromJson(json.decode(str));
String readResponseModelToJson(ReadResponseModel data) => json.encode(data.toJson());
class ReadResponseModel {
ReadResponseModel({
this.status,
this.content,
});
int status;
List<Content> content;
factory ReadResponseModel.fromJson(Map<String, dynamic> json) => ReadResponseModel(
status: json["status"],
content: List<Content>.from(json["content"].map((x) => Content.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"content": List<dynamic>.from(content.map((x) => x.toJson())),
};
}
class Content {
Content({
this.imageId,
this.imageUrl,
this.returnedValue,
this.alarm,
this.account,
this.createAt,
this.location,
});
String imageId;
String imageUrl;
String returnedValue;
String alarm;
String account;
DateTime createAt;
String location;
factory Content.fromJson(Map<String, dynamic> json) => Content(
imageId: json["image_id"],
imageUrl: json["image_url"],
returnedValue: json["returned_value"],
alarm: json["alarm"],
account: json["account"],
createAt: DateTime.parse(json["create_at"]),
location: json["location"],
);
Map<String, dynamic> toJson() => {
"image_id": imageId,
"image_url": imageUrl,
"returned_value": returnedValue,
"alarm": alarm,
"account": account,
"create_at": createAt.toIso8601String(),
"location": location,
};
}
And them main class for fetching the data and showing it in the listview.
import 'package:flutter/material.dart';
import 'package:json_parsing_example/model2.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SampleApp(),
debugShowCheckedModeBanner: false,
);
}
}
class SampleApp extends StatefulWidget {
#override
_SampleAppState createState() => _SampleAppState();
}
class _SampleAppState extends State<SampleApp> {
bool _isLoading = false;
List<Content> list = List();
fetchData() async {
setState(() {
_isLoading = true;
});
String data =
await DefaultAssetBundle.of(context).loadString("json/parse.json");
// This is the above where you get the remote data
// Like var response = await get or post
final readResponseModel = readResponseModelFromJson(data);
list = readResponseModel.content;
setState(() {
_isLoading = false;
});
}
#override
void initState() {
super.initState();
fetchData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your heading'),
),
body: Container(
child: _isLoading
? Center(child: CircularProgressIndicator())
: Column(
children: <Widget>[
ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: <Widget>[
Text('${list[index].account}'),
Text('${list[index].location}')
],
),
);
})
],
)));
}
}
Let me know if it works
Can you try setting returned_value and image_id as int instead of string and give it a try ?
I am using this code to upload json data to my nodejs server.
HttpClient client = new HttpClient();
var data = createSamplePayment().toJson();
var request = await client.openUrl('POST', Uri.parse(serverEndpoint + '/paymentrequests'));
request.headers.set(HttpHeaders.contentTypeHeader, 'APPLICATION/JSON');
request.write(json.encode(data));
var response = await request.close();
String reply = await response.transform(utf8.decoder).join();
print(reply);
The output from print(reply) is:
flutter: {"url":"https://paymentrequests/86C0110D","token":"w8SWavZNjOG","id":"C3C4966AF64D8CE194F5E3C"}
But I only want to get ”token” value. What can I do to fix that? I have tried in many different ways without success.
class DetailsModel {
String url;
String token;
String id;
DetailsModel({this.url, this.token, this.id});
DetailsModel.fromJson(Map<String, dynamic> json) {
url = json['url'];
token = json['token'];
id = json['id'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['url'] = this.url;
data['token'] = this.token;
data['id'] = this.id;
return data;
}
}
Firstly, convert your response into a Model, to do that you would need the above code. Then map your response.
DetailsModel details = DetailsModel.fromJson(response);
Then to access the details you can simply use.
dynamic token = details.token;
print(token); // w8SWavZNjOG
You can copy paste run full code below
I use the following code to simulate this case
You can do payloadFromJson(reply) and return payload.token
You can reference Payload class in full code
code snippet
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
...
Future<String> postWithClientCertificate() async {
...
Payload payload = payloadFromJson(reply);
print(payload.token);
return payload.token;
}
output
I/flutter ( 5995): w8SWavZNjOG
I/flutter ( 5995): token w8SWavZNjOG
full code
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:convert';
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
String payloadToJson(Payload data) => json.encode(data.toJson());
class Payload {
Payload({
this.url,
this.token,
this.id,
});
String url;
String token;
String id;
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
url: json["url"],
token: json["token"],
id: json["id"],
);
Map<String, dynamic> toJson() => {
"url": url,
"token": token,
"id": id,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() async{
String token = await postWithClientCertificate();
print("token $token");
setState(() {
_counter++;
});
}
Future<String> postWithClientCertificate() async {
/*final serverEndpoint = 'https://1991269db78887f9e.ngrok.io';
HttpClient client = new HttpClient();
var data = createSamplePayment().toJson();
var request = await client.openUrl('POST', Uri.parse(serverEndpoint + '/paymentrequests'));
request.headers.set(HttpHeaders.contentTypeHeader, 'APPLICATION/JSON');
request.write(json.encode(data));
var response = await request.close();
String reply = await response.transform(utf8.decoder).join();
print(reply);*/
String reply =
'''{"url":"https://paymentrequests/86C0110D","token":"w8SWavZNjOG","id":"C3C4966AF64D8CE194F5E3C"}''';
Payload payload = payloadFromJson(reply);
print(payload.token);
return payload.token;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
I am getting an API response of the following type
[
{"name":"lakshay","id":"1217","type":"Staff","temperature":56.6,"date":"12-06-2020"},
{"name":"lakshay","id":"1217","type":"Staff","temperature":56.6,"date":"12-06-2020"},
.....
]
I need to parse the whole thing as List of objects, so that I can do something like
// conceptual //
array.map((obj)=>{
// computation //
})
I took help from here but it doesn't tell how to parse the outer array.
thanks for your time.
You can generate expected response class online using below link and create and save class in your project :
https://javiercbk.github.io/json_to_dart/
For more details see this image :
class ApiRepositary {
Dio dio;
ApiRepositary() {
if (dio == null) {
BaseOptions options = new BaseOptions(
baseUrl: "your base url",
receiveDataWhenStatusError: true,
connectTimeout: 60*1000, // 60 seconds
receiveTimeout: 60*1000 // 60 seconds
);
dio = new Dio(options);
}
}
Future<List<UserResponse>> getUserDetails() async {
try {
Response res = await dio.get("/lookup/pollquestion/add your url here");
if (res.data.toString().isEmpty) {
throw Exception();
} else {
final List rawData = jsonDecode(jsonEncode(res.data));
List<UserResponse> response =
rawData.map((f) => UserResponse.fromJson(f)).toList();
return response;
}
} on DioError catch (dioError) {
throw Exception(dioError);
}
}
}
To call service in your class :
ApiRepositary().getUserDetails().then((response){
debugPrint("Login Success $response");
//manage your response here, here you will get arralist as a response
},
onError: (exception){
//Handle exception message
if(exception.message != null ){
debugPrint(exception.message);
}
},
);
You can copy paste run full code below
Step 1: parse with List<Payload> payloadList = payloadFromJson(jsonString); , you can see full code for detail Payload class definition
Step 2: For loop like this
payloadList.forEach((element) {
print(element.name);
print(element.id);
});
output
I/flutter (17660): lakshay
I/flutter (17660): 1217
I/flutter (17660): lakshay
I/flutter (17660): 1217
full code
import 'package:flutter/material.dart';
import 'dart:convert';
List<Payload> payloadFromJson(String str) =>
List<Payload>.from(json.decode(str).map((x) => Payload.fromJson(x)));
String payloadToJson(List<Payload> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Payload {
Payload({
this.name,
this.id,
this.type,
this.temperature,
this.date,
});
String name;
String id;
String type;
double temperature;
String date;
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
name: json["name"],
id: json["id"],
type: json["type"],
temperature: json["temperature"].toDouble(),
date: json["date"],
);
Map<String, dynamic> toJson() => {
"name": name,
"id": id,
"type": type,
"temperature": temperature,
"date": date,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String jsonString = '''
[
{"name":"lakshay","id":"1217","type":"Staff","temperature":56.6,"date":"12-06-2020"},
{"name":"lakshay","id":"1217","type":"Staff","temperature":56.6,"date":"12-06-2020"}
]
''';
void _incrementCounter() {
List<Payload> payloadList = payloadFromJson(jsonString);
payloadList.forEach((element) {
print(element.name);
print(element.id);
});
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Please use this response class
class YourResponse {
String name;
String id;
String type;
double temperature;
String date;
YourResponse({this.name, this.id, this.type, this.temperature, this.date});
YourResponse.fromJson(Map<String, dynamic> json) {
name = json['name'];
id = json['id'];
type = json['type'];
temperature = json['temperature'];
date = json['date'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['id'] = this.id;
data['type'] = this.type;
data['temperature'] = this.temperature;
data['date'] = this.date;
return data;
}
}
Assuming
String jsonResponse = '''[
{"name":"lakshay","id":"1217","type":"Staff","temperature":56.6,"date":"12-06-2020"},
{"name":"lakshay","id":"1217","type":"Staff","temperature":56.6,"date":"12-06-2020"}
]''';
You could do something as below:
Step 1) import 'dart:convert' package.
Step 2 ) Add following lines:
List<dynamic> responses = jsonDecode(jsonResponse);
responses.forEach((obj){
print(obj['name']);
});
Remember the above code is a quick & dirty way get things working.you may lose many benefits of static type checking.It always recommended that use classes created as suggested by chunhunghan.
I use this topology model to parse Json data. The data become garbled when I receive Chinese characters.
I have tried to add utf8.decode like
List<Client> clientFromJson(String str) => List<Client>.from(json.decode(utf8.decode(str)).map((x) => Client.fromJson(x)));
but the IDE tell me that "The argument type 'String' can't be assigned to the parameter type 'List< int >' ".
What should I do to add utf8 decoder in the model?
///topology.dart
// To parse this JSON data, do
//
// final client = clientFromJson(jsonString);
// final topology = topologyFromJson(jsonString);
import 'dart:convert';
List<Client> clientFromJson(String str) => List<Client>.from(json.decode(str).map((x) => Client.fromJson(x)));
String clientToJson(List<Client> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
List<Topology> topologyFromJson(String str) => List<Topology>.from(json.decode(str).map((x) => Topology.fromJson(x)));
String topologyToJson(List<Topology> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Topology {
String location;
String mode;
String macAddress;
String ipAddress;
String downloadSpeed;
String downloadSpeedUnit;
String uploadSpeed;
String uploadSpeedUnit;
List<Client> client;
Topology({
this.location,
this.mode,
this.macAddress,
this.ipAddress,
this.downloadSpeed,
this.downloadSpeedUnit,
this.uploadSpeed,
this.uploadSpeedUnit,
this.client,
});
factory Topology.fromJson(Map<String, dynamic> json) => Topology(
location: json["location"],
mode: json["mode"],
macAddress: json["macAddress"],
ipAddress: json["ipAddress"],
downloadSpeed: json["downloadSpeed"],
downloadSpeedUnit: json["downloadSpeedUnit"],
uploadSpeed: json["uploadSpeed"],
uploadSpeedUnit: json["uploadSpeedUnit"],
client: List<Client>.from(json["client"].map((x) => Client.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"location": location,
"mode": mode,
"macAddress": macAddress,
"ipAddress": ipAddress,
"downloadSpeed": downloadSpeed,
"downloadSpeedUnit": downloadSpeedUnit,
"uploadSpeed": uploadSpeed,
"uploadSpeedUnit": uploadSpeedUnit,
"client": List<dynamic>.from(client.map((x) => x.toJson())),
};
}
class Client {
String hostname;
String macAddress;
String ipAddress;
String deviceType;
String connectedNebula;
String connectionType;
String connectTime;
Client({
this.hostname,
this.macAddress,
this.ipAddress,
this.deviceType,
this.connectedNebula,
this.connectionType,
this.connectTime,
});
factory Client.fromJson(Map<String, dynamic> json) => Client(
hostname: json["hostname"],
macAddress: json["macAddress"],
ipAddress: json["ipAddress"],
deviceType: json["deviceType"],
connectedNebula: json["connectedNebula"],
connectionType: json["connectionType"],
connectTime: json["connectTime"],
);
Map<String, dynamic> toJson() => {
"hostname": hostname,
"macAddress": macAddress,
"ipAddress": ipAddress,
"deviceType": deviceType,
"connectedNebula": connectedNebula,
"connectionType": connectionType,
"connectTime": connectTime,
};
}
//main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Topology',
theme: ThemeData(),
home: Home(),
);
}
}
class Home extends StatefulWidget {
final String title;
const Home({Key key, this.title}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
var topologies = const [];
Future loadTopologyList() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String managementPassword = prefs.getString("management_password");
String username = 'admin';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$managementPassword'));
final String url ="some url";
bool trustSelfSigned = true;
HttpClient httpClient = HttpClient()
..badCertificateCallback =
((X509Certificate cert, String host, int port) => trustSelfSigned);
IOClient ioClient = IOClient(httpClient);
final response = await ioClient.get(url,
headers: <String, String>{'authorization': basicAuth},
);
ioClient.close();
String content = response.body;
setState(() {
topologies = topologyFromJson(content);
});
}
void initState() {
loadTopologyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFFAFAFA),
appBar: AppBar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(17, 0, 0, 0),
child: Text('Topology'),
),
Expanded(
child: ListView.separated(
itemCount: topologies.length,
separatorBuilder: (context, index) => Divider(),
itemBuilder: (BuildContext context, int index) {
Topology topology = topologies[index];
return ListTile(
title: Text(
topology.location,
),
leading: CircleAvatar(
child: Image.asset(
"assets/drawable-mdpi/app_icon_circle.png")),
onTap: () {
},
);
},
),
),
],
),
);
}
}
You have to pass the response.bodyBytes when using utf8.decode.
For example:
json.decode(utf8.decode(response.bodyBytes))
and If you got a String then you can use below code to decode.
utf8.decode(someString.runes.toList()),
I got this error:
Unhandled Exception: type 'List' is not a subtype of type 'String'
I got this error when I modify the topology.dart
List<Client> clientFromJson(String str) => List<Client>.from(json.decode(utf8.decode(str.runes.toList())).map((x) => Client.fromJson(x)));
String clientToJson(List<Client> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
List<Topology> topologyFromJson(String str) => List<Topology>.from(json.decode(utf8.decode(str.runes.toList())).map((x) => Topology.fromJson(x)));
String topologyToJson(List<Topology> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
and in the main.dart
final json = jsonDecode(utf8.decode(response.bodyBytes));
setState(() {
topologies = topologyFromJson(json);
});
Getting below Format exception when I am trying to decode Json response. Please help out.
Unhandled Exception: FormatException: Unexpected character (at character 3)
[{table_no: 1}, {table_no: 2}, {table_no: 3}]
[
{
"table_no": "1"
},
{
"table_no": "2"
},
{
"table_no": "3"
}
]
Future<Response> pos_client_table() async {
String url =
'https://xxxxxx.com/api/v1/table?branch_id=1';
Response response;
Dio dio = new Dio();
dio.options.headers = {'Authorization': prefs.getString('posclient_token')};
try {
response = await dio.get(url);
var jso = json.decode(response.toString());
Fluttertoast.showToast(
msg: "$jso",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIos: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
} catch (e) {
print(e);
}
return response;
}
void CallTableUrl() async {
Response response = await pos_client_table();
List<Map> _myJson = json.decode(response.toString());
showInSnackBar('$_myJson');
}
Edit add dio parse example and parse picture
Response response;
Dio dio = new Dio();
response = await dio.get("http://yoursite");
print(response);
print(response.data.toString());
List<Payload> payload = payloadFromJson(response.data);
print({payload[0].tableNo});
Assume dio already return correct json string is
String jsonString = '[{"table_no": "1"},{"table_no": "2"},{"table_no": "3"}]';
Step 1: Parse jsonString with payload class
List<Payload> payload = payloadFromJson(jsonString);
payload class
List<Payload> payloadFromJson(String str) =>
List<Payload>.from(json.decode(str).map((x) => Payload.fromJson(x)));
String payloadToJson(List<Payload> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Payload {
String tableNo;
Payload({
this.tableNo,
});
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
tableNo: json["table_no"],
);
Map<String, dynamic> toJson() => {
"table_no": tableNo,
};
}
Step 2: transfer this payload to required map of DropdownMenuItem
for (var i = 0; i < payload.length; i++) {
_myJson.add({'id': payload[i].tableNo, 'name': payload[i].tableNo});
}
Step 3: populate DropdownMenuItem
DropdownButton<String>(
isDense: true,
hint: Text("${payload[0].tableNo}"),
value: _mySelection,
onChanged: (String Value) {
setState(() {
_mySelection = Value;
});
print(_mySelection);
},
items: _myJson.map((Map map) {
return DropdownMenuItem<String>(
value: map["id"].toString(),
child: Text(
map["name"],
),
);
}).toList(),
),
full code
import 'package:flutter/material.dart';
import 'dart:convert';
List<Payload> payloadFromJson(String str) =>
List<Payload>.from(json.decode(str).map((x) => Payload.fromJson(x)));
String payloadToJson(List<Payload> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Payload {
String tableNo;
Payload({
this.tableNo,
});
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
tableNo: json["table_no"],
);
Map<String, dynamic> toJson() => {
"table_no": tableNo,
};
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
String jsonString = '[{"table_no": "1"},{"table_no": "2"},{"table_no": "3"}]';
List<Payload> payload = payloadFromJson(jsonString);
List<Map> _myJson = [];
class _MyHomePageState extends State<MyHomePage> {
String _mySelection;
#override
void initState() {
for (var i = 0; i < payload.length; i++) {
_myJson.add({'id': payload[i].tableNo, 'name': payload[i].tableNo});
}
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Container(
height: 500.0,
child: Center(
child: DropdownButton<String>(
isDense: true,
hint: Text("${payload[0].tableNo}"),
value: _mySelection,
onChanged: (String Value) {
setState(() {
_mySelection = Value;
});
print(_mySelection);
},
items: _myJson.map((Map map) {
return DropdownMenuItem<String>(
value: map["id"].toString(),
child: Text(
map["name"],
),
);
}).toList(),
),
),
),
],
),
),
);
}
}