Parse JSON in flutter, show data in label - flutter

i have this json:
[
{
"id": 988846211,
"serviceTag": "1LJVKS2",
"orderBuid": 1212,
"shipDate": "2019-04-11T00:00:00Z",
"productCode": ";E403",
"localChannel": "ENTP",
"productId": "dell-u2719d-monitor",
"productLineDescription": "DELL ULTRASHARP U2719D",
"productFamily": "Unknown",
"systemDescription": "Dell U2719D",
"productLobDescription": "Displays",
"countryCode": "SE",
"duplicated": false,
"invalid": false,
"entitlements": [
{
"itemNumber": "709-15308",
"startDate": "2019-04-11T00:00:00Z",
"endDate": "2022-04-11T23:59:59.999Z",
"entitlementType": "INITIAL",
"serviceLevelCode": "ND",
"serviceLevelDescription": "C, NBD ONSITE",
"serviceLevelGroup": 5
},
{
"itemNumber": "865-41964",
"startDate": "2019-04-11T00:00:00Z",
"endDate": "2023-04-11T23:59:59.999Z",
"entitlementType": "INITIAL",
"serviceLevelCode": "ND",
"serviceLevelDescription": "C, NBD ONSITE",
"serviceLevelGroup": 5
}
]
}
]
and my main :
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:dell_warranty/dellTok.dart';
import 'package:dell_warranty/model_json.dart';
void main() => runApp(new MaterialApp(
home: new DellW(),
));
class DellW extends StatefulWidget {
#override
DellWState createState() => new DellWState();
}
class DellWState extends State<DellW> {
TextEditingController serviceTagg = TextEditingController();
final String getToken = "https://apigtwb2c.us.dell.com/auth/oauth/v2/token";
final String apiUrl =
"https://apigtwb2c.us.dell.com/PROD/sbil/eapi/v5/asset-entitlements";
String tagg;
DellTok dellTok;
ModelJson modelJson;
String disc = "";
List<ModelJson> data = [];
#override
void initState() {
super.initState();
this.checkDell();
}
checkDell() async {
var responseToken = await http.post(Uri.encodeFull(getToken), body: {
"grant_type": "client_credentials",
"client_id": "SECRET",
"client_secret": "SECRET"
});
if (responseToken.statusCode == 200) {
var responseTok = json.decode(responseToken.body);
dellTok = DellTok.fromJson(responseTok);
print(responseTok);
setState(() {});
} else {
print(responseToken.statusCode);
}
}
checkDellTagg(String serviceTag) async {
var queryParameters = {
'access_token': dellTok.accessToken,
'servicetags': serviceTag,
};
var uri = Uri.https('apigtwb2c.us.dell.com',
'/PROD/sbil/eapi/v5/asset-entitlements', queryParameters);
var responseDell = await http.get(uri, headers: {});
if (responseDell.statusCode == 200) {
List<dynamic> responseD = jsonDecode(responseDell.body);
List<ModelJson> modelJsonRes =
responseD.map((responseD) => ModelJson.fromJson(responseD)).toList();
setState(() {
disc = modelJson.productLineDescription;
});
} else {
print(responseDell.statusCode);
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Dell Warranty"),
),
body: dellTok == null
? Center(
child: CircularProgressIndicator(),
)
: Container(
padding: EdgeInsets.all(20.0),
child: Column(
children: [
RaisedButton(
onPressed: () => checkDellTagg(serviceTagg.text),
child: Text(
"Flat Button",
)),
TextField(
decoration:
InputDecoration(hintText: "write servicetag..."),
controller: serviceTagg,
),
Text(disc),
],
)));
}
}
and my model_json.dart file :
class ModelJson {
int id;
String serviceTag;
int orderBuid;
String shipDate;
String productCode;
String localChannel;
String productId;
String productLineDescription;
String productFamily;
String systemDescription;
String productLobDescription;
String countryCode;
bool duplicated;
bool invalid;
List<Entitlements> entitlements;
ModelJson(
{this.id,
this.serviceTag,
this.orderBuid,
this.shipDate,
this.productCode,
this.localChannel,
this.productId,
this.productLineDescription,
this.productFamily,
this.systemDescription,
this.productLobDescription,
this.countryCode,
this.duplicated,
this.invalid,
this.entitlements});
ModelJson.fromJson(Map<String, dynamic> json) {
id = json['id'];
serviceTag = json['serviceTag'];
orderBuid = json['orderBuid'];
shipDate = json['shipDate'];
productCode = json['productCode'];
localChannel = json['localChannel'];
productId = json['productId'];
productLineDescription = json['productLineDescription'];
productFamily = json['productFamily'];
systemDescription = json['systemDescription'];
productLobDescription = json['productLobDescription'];
countryCode = json['countryCode'];
duplicated = json['duplicated'];
invalid = json['invalid'];
if (json['entitlements'] != null) {
entitlements = new List<Entitlements>();
json['entitlements'].forEach((v) {
entitlements.add(new Entitlements.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['serviceTag'] = this.serviceTag;
data['orderBuid'] = this.orderBuid;
data['shipDate'] = this.shipDate;
data['productCode'] = this.productCode;
data['localChannel'] = this.localChannel;
data['productId'] = this.productId;
data['productLineDescription'] = this.productLineDescription;
data['productFamily'] = this.productFamily;
data['systemDescription'] = this.systemDescription;
data['productLobDescription'] = this.productLobDescription;
data['countryCode'] = this.countryCode;
data['duplicated'] = this.duplicated;
data['invalid'] = this.invalid;
if (this.entitlements != null) {
data['entitlements'] = this.entitlements.map((v) => v.toJson()).toList();
}
return data;
}
}
class Entitlements {
String itemNumber;
String startDate;
String endDate;
String entitlementType;
String serviceLevelCode;
String serviceLevelDescription;
int serviceLevelGroup;
Entitlements(
{this.itemNumber,
this.startDate,
this.endDate,
this.entitlementType,
this.serviceLevelCode,
this.serviceLevelDescription,
this.serviceLevelGroup});
Entitlements.fromJson(Map<String, dynamic> json) {
itemNumber = json['itemNumber'];
startDate = json['startDate'];
endDate = json['endDate'];
entitlementType = json['entitlementType'];
serviceLevelCode = json['serviceLevelCode'];
serviceLevelDescription = json['serviceLevelDescription'];
serviceLevelGroup = json['serviceLevelGroup'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['itemNumber'] = this.itemNumber;
data['startDate'] = this.startDate;
data['endDate'] = this.endDate;
data['entitlementType'] = this.entitlementType;
data['serviceLevelCode'] = this.serviceLevelCode;
data['serviceLevelDescription'] = this.serviceLevelDescription;
data['serviceLevelGroup'] = this.serviceLevelGroup;
return data;
}
}
I'm trying to show the data in text field .
everthing ok when i post to get an access token and its saved and i used it to make a get req to the other url so i can get the data.
example :
i want to show
productLineDescription
in text widget.
but im not going any farther than that!
how i am supposed to get data from model_json.dart and show it inside text widget?
sorry i am flutter newbie, thanks for the help.

If you want to get the productLineDescription, you have to call it like this:
productLineDescription = jsonDecode(myJson)[0]['productLineDescription'];
NOTE: myJson is your json source file.
You need the [0] because your json is inside a List.

Related

Pagination new data Isn't added to the ListView.builder at the end instead refreshed replacing previous data

I have an API from where I am get 10 data entries on each hit. What I want to do is to add these entries at the end of the ListView.builder List. At the moment it refreshes the ListView.builder instead of populating more entries.
Code for the whole screen is quite longer so I trimmed down only for one type of entry.
class PaginatedScreen extends StatefulWidget {
const PaginatedScreen({Key? key}) : super(key: key);
#override
State<PaginatedScreen> createState() => _PaginatedScreenState();
}
class _PaginatedScreenState extends State<PaginatedScreen> {
final scrollController = ScrollController();
int offSetCurrent = 0;
bool hasMore = true;
bool isLoading = false;
#override
void initState(){
super.initState();
scrollController.addListener(() {
if (scrollController.position.maxScrollExtent == scrollController.offset) {
setState(() {
getDiscussion(offSetCurrent);
print('initial offSet: $offSetCurrent');
offSetCurrent = offSetCurrent + 10;
print('new offset $offSetCurrent');
});
}
});
}
#override
void dispose(){
scrollController.dispose();
super.dispose();
}
Future<PaginatedModel> getDiscussion(offSetCurrent) async {
// if (isLoading) return;
// isLoading = true;
SharedPreferences sp = await SharedPreferences.getInstance();
var parameters = {
'RangeFrom':offSetCurrent.toString(),
'AccessToken':sp.getString('AccessToken'),
'DiscussionID':'22848',
};
var urlfetch = Uri(
scheme: "https",
host: baseUrl,
path: discussionAPIPath,
queryParameters: parameters,
);
try {
http.Response response = await http.get(Uri.parse(urlfetch.toString()));
var data = jsonDecode(response.body.toString());
var snapshot = PaginatedModel.fromJson(data);
var itemsTotal = snapshot.courseLessonDetailsData!.first.discussionDetails!.first.discussionsMessages!.length;
if (itemsTotal < 10){
setState((){
hasMore = false;
});
}
print(data);
print('Discussion API HIT with offset $offSetCurrent');
// isLoading = false;
if (response.statusCode == 200) {
return PaginatedModel.fromJson(data);
}
else {
print(response.statusCode);
return PaginatedModel.fromJson(data);
}
}
catch (e) {
print(e.toString());
rethrow;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: getDiscussion(offSetCurrent),
builder: (dCtx, dSnapshot){
if (dSnapshot.hasData){
var itemCount = dSnapshot.data!.courseLessonDetailsData!.first.discussionDetails!.first.discussionsMessages!.length;
return ListView.builder(
controller: scrollController,
shrinkWrap: true,
itemCount: itemCount + 1,
itemBuilder: (context, idx){
if (idx < itemCount){
return Column(
children: List<Widget>.generate(dSnapshot.data!.courseLessonDetailsData!.first.discussionDetails!.length, (i) => Container(
margin: const EdgeInsets.all(10),
child: Column(
children: [
Html(data: dSnapshot.data!.courseLessonDetailsData!.first.discussionDetails!.first.discussionsMessages![idx].message.toString()),
],
),
))
);
}
else {
return Padding(
padding: EdgeInsets.symmetric(vertical: 32),
child: Center(
child: hasMore? CircularProgressIndicator() : Text('No More Data'),
),
);
}
}
);
}
else {
return const Center(
child: CircularProgressIndicator(),
);
}
}
),
);
}
}
Here is my Model:
class PaginatedModel {
PaginatedModel({
List<CourseLessonDetailsData>? courseLessonDetailsData,}){
_courseLessonDetailsData = courseLessonDetailsData;
}
PaginatedModel.fromJson(dynamic json) {
if (json['CourseLessonDetailsData'] != null) {
_courseLessonDetailsData = [];
json['CourseLessonDetailsData'].forEach((v) {
_courseLessonDetailsData?.add(CourseLessonDetailsData.fromJson(v));
});
}
}
List<CourseLessonDetailsData>? _courseLessonDetailsData;
PaginatedModel copyWith({ List<CourseLessonDetailsData>? courseLessonDetailsData,
}) => PaginatedModel( courseLessonDetailsData: courseLessonDetailsData ?? _courseLessonDetailsData,
);
List<CourseLessonDetailsData>? get courseLessonDetailsData => _courseLessonDetailsData;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
if (_courseLessonDetailsData != null) {
map['CourseLessonDetailsData'] = _courseLessonDetailsData?.map((v) => v.toJson()).toList();
}
return map;
}
}
class CourseLessonDetailsData {
CourseLessonDetailsData({
String? requestStatus,
List<DiscussionDetails>? discussionDetails,}){
_requestStatus = requestStatus;
_discussionDetails = discussionDetails;
}
CourseLessonDetailsData.fromJson(dynamic json) {
_requestStatus = json['request_status'];
if (json['DiscussionDetails'] != null) {
_discussionDetails = [];
json['DiscussionDetails'].forEach((v) {
_discussionDetails?.add(DiscussionDetails.fromJson(v));
});
}
}
String? _requestStatus;
List<DiscussionDetails>? _discussionDetails;
CourseLessonDetailsData copyWith({ String? requestStatus,
List<DiscussionDetails>? discussionDetails,
}) => CourseLessonDetailsData( requestStatus: requestStatus ?? _requestStatus,
discussionDetails: discussionDetails ?? _discussionDetails,
);
String? get requestStatus => _requestStatus;
List<DiscussionDetails>? get discussionDetails => _discussionDetails;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['request_status'] = _requestStatus;
if (_discussionDetails != null) {
map['DiscussionDetails'] = _discussionDetails?.map((v) => v.toJson()).toList();
}
return map;
}
}
class DiscussionDetails {
DiscussionDetails({
List<DiscussionsMessages>? discussionsMessages,}){
_discussionsMessages = discussionsMessages;
}
DiscussionDetails.fromJson(dynamic json) {
if (json['DiscussionsMessages'] != null) {
_discussionsMessages = [];
json['DiscussionsMessages'].forEach((v) {
_discussionsMessages?.add(DiscussionsMessages.fromJson(v));
});
}
}
List<DiscussionsMessages>? _discussionsMessages;
DiscussionDetails copyWith({ List<DiscussionsMessages>? discussionsMessages,
}) => DiscussionDetails( discussionsMessages: discussionsMessages ?? _discussionsMessages,
);
List<DiscussionsMessages>? get discussionsMessages => _discussionsMessages;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
if (_discussionsMessages != null) {
map['DiscussionsMessages'] = _discussionsMessages?.map((v) => v.toJson()).toList();
}
return map;
}
}
class DiscussionsMessages {
DiscussionsMessages({
String? messageID,
String? id,
String? studentName,
String? message,
String? replyMessage,
List<OtherStudentMessages>? otherStudentMessages,}){
_messageID = messageID;
_id = id;
_studentName = studentName;
_message = message;
_replyMessage = replyMessage;
_otherStudentMessages = otherStudentMessages;
}
DiscussionsMessages.fromJson(dynamic json) {
_messageID = json['MessageID'];
_id = json['ID'];
_studentName = json['StudentName'];
_message = json['Message'];
_replyMessage = json['ReplyMessage'];
if (json['OtherStudentMessages'] != null) {
_otherStudentMessages = [];
json['OtherStudentMessages'].forEach((v) {
_otherStudentMessages?.add(OtherStudentMessages.fromJson(v));
});
}
}
String? _messageID;
String? _id;
String? _studentName;
String? _message;
String? _replyMessage;
List<OtherStudentMessages>? _otherStudentMessages;
DiscussionsMessages copyWith({ String? messageID,
String? id,
String? studentName,
String? message,
String? replyMessage,
List<OtherStudentMessages>? otherStudentMessages,
}) => DiscussionsMessages( messageID: messageID ?? _messageID,
id: id ?? _id,
studentName: studentName ?? _studentName,
message: message ?? _message,
replyMessage: replyMessage ?? _replyMessage,
otherStudentMessages: otherStudentMessages ?? _otherStudentMessages,
);
String? get messageID => _messageID;
String? get id => _id;
String? get studentName => _studentName;
String? get message => _message;
String? get replyMessage => _replyMessage;
List<OtherStudentMessages>? get otherStudentMessages => _otherStudentMessages;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['MessageID'] = _messageID;
map['ID'] = _id;
map['StudentName'] = _studentName;
map['Message'] = _message;
map['ReplyMessage'] = _replyMessage;
if (_otherStudentMessages != null) {
map['OtherStudentMessages'] = _otherStudentMessages?.map((v) => v.toJson()).toList();
}
return map;
}
}
class OtherStudentMessages {
OtherStudentMessages({
String? replyID,
String? repliedBy,
String? replyMessage,}){
_replyID = replyID;
_repliedBy = repliedBy;
_replyMessage = replyMessage;
}
OtherStudentMessages.fromJson(dynamic json) {
_replyID = json['ReplyID'];
_repliedBy = json['RepliedBy'];
_replyMessage = json['ReplyMessage'];
}
String? _replyID;
String? _repliedBy;
String? _replyMessage;
OtherStudentMessages copyWith({ String? replyID,
String? repliedBy,
String? replyMessage,
}) => OtherStudentMessages( replyID: replyID ?? _replyID,
repliedBy: repliedBy ?? _repliedBy,
replyMessage: replyMessage ?? _replyMessage,
);
String? get replyID => _replyID;
String? get repliedBy => _repliedBy;
String? get replyMessage => _replyMessage;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['ReplyID'] = _replyID;
map['RepliedBy'] = _repliedBy;
map['ReplyMessage'] = _replyMessage;
return map;
}
}
And here is the JSON response from the API. (with one entry)
{
"CourseLessonDetailsData": [
{
"request_status": "Successful",
"DiscussionDetails": [
{
"DiscussionsMessages": [
{
"MessageID": "301",
"ID": "48",
"StudentName": "Person Name",
"Message": "This is from Message",
"ReplyMessage": "This is a Reply Message",
"OtherStudentMessages": [
{
"ReplyID":"939",
"RepliedBy":"Reply Person",
"ReplyMessage":"resubmit means you can submit again if you want until the deadline is over"
}
]
}
]
}
]
}
]
}
I edited your code but could not test it out, please check it if it works.
You need to make a list variable that will hold all your paginated data. Then call your future and then after result is not null, add it to your list and change your loading status to false. After, use scrolls and scrollListener reaches max extent, change offset and call your api again and after result is not null, again add to your list.
class PaginatedScreen extends StatefulWidget {
const PaginatedScreen({Key? key}) : super(key: key);
#override
State<PaginatedScreen> createState() => _PaginatedScreenState();
}
class _PaginatedScreenState extends State<PaginatedScreen> {
final scrollController = ScrollController();
int offSetCurrent = 0;
bool hasMore = true;
bool isLoading = true;
List<PaginatedModel> listOfData = <PaginatedModel>[];
#override
void initState() async {
super.initState();
var result = await getDiscussion(offSetCurrent);
if (result != null) {
setState(() {
listOfData.add(result);
isLoading = false;
});
}
scrollController.addListener(() async {
if (scrollController.position.maxScrollExtent == scrollController.offset) {
offSetCurrent = offSetCurrent + 10;
setState(() {
isLoading = true;
});
var result = await getDiscussion(offSetCurrent);
setState(() {
listOfData.add(result!);
isLoading = false;
});
}
});
}
#override
void dispose(){
scrollController.dispose();
super.dispose();
}
Future<PaginatedModel?> getDiscussion(offSetCurrent) async {
// if (isLoading) return;
// isLoading = true;
SharedPreferences sp = await SharedPreferences.getInstance();
var parameters = {
'RangeFrom':offSetCurrent.toString(),
'AccessToken':sp.getString('AccessToken'),
'DiscussionID':'22848',
};
var urlfetch = Uri(
scheme: "https",
host: baseUrl,
path: discussionAPIPath,
queryParameters: parameters,
);
try {
http.Response response = await http.get(Uri.parse(urlfetch.toString()));
var data = jsonDecode(response.body.toString());
var snapshot = PaginatedModel.fromJson(data);
var itemsTotal = snapshot.courseLessonDetailsData!.first.discussionDetails!.first.discussionsMessages!.length;
if (itemsTotal < 10){
setState((){
hasMore = false;
});
}
print(data);
print('Discussion API HIT with offset $offSetCurrent');
// isLoading = false;
if (response.statusCode == 200) {
return PaginatedModel.fromJson(data);
}
else {
print(response.statusCode);
return null;
}
}
catch (e) {
print(e.toString());
rethrow;
// return null;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: isLoading
? CircularProgressIndicator()
: ListView.builder(
itemCount: listOfData.length,
itemBuilder: (context, index) {
//do your widget building here
// do whatever you did in your future builder here
return Text(listOfData[index].courseLessonDetailsData![0].requestStatus!);
},
),
// body: FutureBuilder(
// future: getDiscussion(offSetCurrent),
// builder: (dCtx, dSnapshot){
// if (dSnapshot.hasData){
// var itemCount = dSnapshot.data!.courseLessonDetailsData!.first.discussionDetails!.first.discussionsMessages!.length;
// return ListView.builder(
// controller: scrollController,
// shrinkWrap: true,
// itemCount: itemCount + 1,
// itemBuilder: (context, idx){
// if (idx < itemCount){
// return Column(
// children: List<Widget>.generate(dSnapshot.data!.courseLessonDetailsData!.first.discussionDetails!.length, (i) => Container(
// margin: const EdgeInsets.all(10),
// child: Column(
// children: [
// Html(data: dSnapshot.data!.courseLessonDetailsData!.first.discussionDetails!.first.discussionsMessages![idx].message.toString()),
// ],
// ),
// ))
// );
// }
// else {
// return Padding(
// padding: EdgeInsets.symmetric(vertical: 32),
// child: Center(
// child: hasMore? CircularProgressIndicator() : Text('No More Data'),
// ),
// );
// }
// }
// );
// }
// else {
// return const Center(
// child: CircularProgressIndicator(),
// );
// }
// }
// ),
);
}
}

flutter, how to compare the argument passed (id) equal an element.id ? using getx package

I have Categories, and each category contains multiple and different subcategories.
I passed the Id of Categories to the other screen.
First Screen:
onTap: (() => Get.to(const CategoryDetails(), arguments: {
"id":" ${categoriesController.cat!.elementAt(i).sId.toString()} ", })),
ArgumentController
import 'package:get/get.dart';
class ArgumentController extends GetxController {
String? id;
#override
void onInit() {
id = Get.arguments['id'];
super.onInit();
}
}
View File
class _CategoryDetailsState extends State<CategoryDetails> {
int selectedCategoryIndex = 0;
CategoriesController categoriesController = Get.put(CategoriesController());
#override
void initState() {
super.initState();
categoriesController.getCategoriesFromApi();
}
#override
Widget build(BuildContext context) {
ArgumentController controller = Get.put(ArgumentController());
debugPrint(controller.id);
return Scaffold(
appBar: AppBar(
title: const Text("Category Details"),
),
body: Column(
children: [
Text("${controller.id}"),
const Text("data"),
ListView.builder(itemBuilder: (context, index) {
return Column(
children: [
Text(categoriesController.cat!
.elementAt(index)
.subcategories!
.elementAt(selectedCategoryIndex)
.name
.toString()),
],
);
})
],
),
);
}
}
Controller file:
import 'dart:convert';
import 'dart:io';
import 'package:get/get.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import '../model/categoriesmodel.dart' as categories_model;
class CategoriesController extends GetxController {
Iterable<categories_model.Response>? cat;
var isDataLoading = false.obs;
getCategoriesFromApi() async {
try {
isDataLoading(true);
http.Response response = await http.post(
Uri.tryParse('-----')!,
headers: {
HttpHeaders.authorizationHeader: '-------',
});
if (response.statusCode == 200) {
var result = jsonDecode(response.body);
cat = categories_model.Categories.fromJson(result).response;
} else {}
} catch (e) {
debugPrint("Error while getting Data $e");
} finally {
isDataLoading(false);
}
}
}
Categoriesmodel file
class Categories {
String? status;
List<Response>? response;
Categories({this.status, this.response});
Categories.fromJson(Map<String, dynamic> json) {
status = json['status'];
if (json['response'] != null) {
response = <Response>[];
json['response'].forEach((v) {
response!.add(Response.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['status'] = status;
if (response != null) {
data['response'] = response!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Response {
String? sId;
String? name;
bool? isForAccessories;
String? slug;
List<void>? liveTranslations;
String? icon;
String? logo;
int? itemsCount;
String? lang;
List<Subcategories>? subcategories;
Response(
{this.sId,
this.name,
this.isForAccessories,
this.slug,
this.liveTranslations,
this.icon,
this.logo,
this.itemsCount,
this.lang,
this.subcategories});
Response.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
name = json['name'];
isForAccessories = json['isForAccessories'];
slug = json['slug'];
// if (json['liveTranslations'] != null) {
// liveTranslations = <Null>[];
// json['liveTranslations'].forEach((v) {
// liveTranslations!.add(Null.fromJson(v));
// });
// }
icon = json['icon'];
logo = json['logo'];
itemsCount = json['itemsCount'];
lang = json['lang'];
if (json['subcategories'] != null) {
subcategories = <Subcategories>[];
json['subcategories'].forEach((v) {
subcategories!.add(Subcategories.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['_id'] = sId;
data['name'] = name;
data['isForAccessories'] = isForAccessories;
data['slug'] = slug;
// if (liveTranslations != null) {
// data['liveTranslations'] =
// liveTranslations!.map((v) => v.toJson()).toList();
// }
data['icon'] = icon;
data['logo'] = logo;
data['itemsCount'] = itemsCount;
data['lang'] = lang;
if (subcategories != null) {
data['subcategories'] =
subcategories!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Subcategories {
String? sId;
String? name;
bool? isForAccessories;
String? slug;
List<void>? liveTranslations;
int? itemsCount;
String? lang;
Subcategories(
{this.sId,
this.name,
this.isForAccessories,
this.slug,
this.liveTranslations,
this.itemsCount,
this.lang});
Subcategories.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
name = json['name'];
isForAccessories = json['isForAccessories'];
slug = json['slug'];
// if (json['liveTranslations'] != null) {
// liveTranslations = <Null>[];
// json['liveTranslations'].forEach((v) {
// liveTranslations!.add(Null.fromJson(v));
// });
// }
itemsCount = json['itemsCount'];
lang = json['lang'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['_id'] = sId;
data['name'] = name;
data['isForAccessories'] = isForAccessories;
data['slug'] = slug;
// if (liveTranslations != null) {
// data['liveTranslations'] =
// liveTranslations!.map((v) => v.toJson()).toList();
// }
data['itemsCount'] = itemsCount;
data['lang'] = lang;
return data;
}
}
The problem is in selectedCategoryIndex, how to express that
selectedCategoryIndex == categoriesController.Where((element) => element.sid == the argument passed);
note that it's not acceptable categoriesController.Where..
I just assumed your question to be what I think and posting this solution.
selectedCategoryIndex ==
categoriesController.cat.singleWhere((element) => element.id == id).sId;

Parsing json to model fails in flutter

I am trying to show data to listview but it doesn't show anything.there is json below ,am i doing something wrong,i tired to print the data in api call but i can print the data but not in the listview,
i having hardtime to understand what i doing wrong or correct.please help me on this
if (response.statusCode == 200) {
try {
if (status == true) {
var company_list = value['doc'];
for (int i = 0; i < company_list.length; i++) {
print(company_list);
var mobile_list = company_list["mobile"];
var email_list = company_list["email"];
company_model.add(CompanyModel.fromJson(company_list,mobile_list,email_list));
}
setState(() {
print("UI Updated");
});
} else {
final snackBar = SnackBar(content: Text(message));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
} catch (e) {
e.toString();
}
} else {
final snackBar = SnackBar(content: Text(message));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
Json
{
"status":true,
"doc":{
"mobile":[
"9961256754",
"8974525672"
],
"email":[
],
"_id":"5f3a0dfe88b9d50453e92133",
"name":"MRC Labour",
"terms":{
"english":"We Shall not be liable for any disputes arising between the users and the
labourers",
"malayalam":"We Shall not be liable for any disputes arising between the users and the
labourers"
}
}
}
Model
class CompanyModel {
String id = "";
String mobile = "";
String email = "";
String name = "";
String english = "";
String malayalam = "";
CompanyModel({this.id, this.mobile, this.email, this.name, this.english,this.malayalam});
CompanyModel.fromJson(json,mobile_list,email_list)
: id = json['_id'].toString(),
mobile = mobile_list,
email = email_list,
name = json['name'].toString(),
english = json['terms']['english'].toString(),
malayalam = json['terms']['malayalam'].toString();
}
When the debugger hit at this line it breaks without any errors company_model.add(CompanyModel.fromJson(data,mobile_list,email_list));
This is listview code
Container(
height: 80,
width: 100,
color: Colors.blueGrey[100],
padding: EdgeInsets.all(10),
child: ListView.separated(
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
itemCount: company_model.length,
itemBuilder: (BuildContext context, int index) {
CompanyModel data = company_model[index];
print(data);
return Container(
height: 10,
color: Colors.green,
child: Text(data.name.toString(),style: TextStyle(color: Colors.black),),
);
},
),
),
First of all, your model is wrong, you're parsing a List (mobile and email) as a String in your model, also, you don't really need to pass 2 additional parameters to the function.
class CompanyModel {
List<String> mobile;
List<String> email;
String sId;
String name;
Terms terms;
CompanyModel({this.mobile, this.email, this.sId, this.name, this.terms});
CompanyModel.fromJson(Map<String, dynamic> json) {
mobile = json['mobile'].cast<String>();
email = json['email'].cast<String>();
sId = json['_id'];
name = json['name'];
terms = json['terms'] != null ? new Terms.fromJson(json['terms']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['mobile'] = this.mobile;
data['email'] = this.email;
data['_id'] = this.sId;
data['name'] = this.name;
if (this.terms != null) {
data['terms'] = this.terms.toJson();
}
return data;
}
}
class Terms {
String english;
String malayalam;
Terms({this.english, this.malayalam});
Terms.fromJson(Map<String, dynamic> json) {
english = json['english'];
malayalam = json['malayalam'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['english'] = this.english;
data['malayalam'] = this.malayalam;
return data;
}
}
Also, double check that you're initializing the company_model as something like: List company_model = [] otherwise it initialize as null and won't work the rest of your code.
if (response.statusCode == 200) {
try {
if (status == true) {
var company_json = value['doc'];
company_model.add(CompanyModel.fromJson(company_json));
setState(() {
print("UI Updated");
});
} else {
final snackBar = SnackBar(content: Text(message));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
} catch (e) {
e.toString();
}
} else {
final snackBar = SnackBar(content: Text(message));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
The best way to create model is in the link below
https://app.quicktype.io/
just put your json on as input on left side and select dart as language from left, you are good to go.

type 'List<dynamic>' is not a subtype of type 'String'

It contains lots of list and nested objects. I need to display all the DishName from the json file
Json URL adress : Json address!! Check this out
i wanted to display the DishName in to my app in which there are lots of dishname in the json list.
i parsed the json file using instantly parse json website.
But now i dont know how to implent it on my app
code i wrote :
body: Container(
child: Center(
child: FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString('jsons/data.json'),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
var myData = jsonDecode(snapshot.data);
final welcome = welcomeFromJson(myData);
print(myData.length);
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text(welcome[index]
.tableMenuList[index]
.categoryDishes[index]
.dishName),
));
},
itemCount: myData == null ? 0 : myData.length,
);
},
),
),
),
i am getting error : type 'List' is not a subtype of type 'String'
this is the json class:-
// To parse this JSON data, do
//
// final welcome = welcomeFromJson(jsonString);
import 'dart:convert';
List<Welcome> welcomeFromJson(String str) =>
List<Welcome>.from(json.decode(str).map((x) => Welcome.fromJson(x)));
String welcomeToJson(List<Welcome> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Welcome {
String restaurantId;
String restaurantName;
String restaurantImage;
String tableId;
String tableName;
String branchName;
String nexturl;
List<TableMenuList> tableMenuList;
Welcome({
this.restaurantId,
this.restaurantName,
this.restaurantImage,
this.tableId,
this.tableName,
this.branchName,
this.nexturl,
this.tableMenuList,
});
factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
restaurantId: json["restaurant_id"],
restaurantName: json["restaurant_name"],
restaurantImage: json["restaurant_image"],
tableId: json["table_id"],
tableName: json["table_name"],
branchName: json["branch_name"],
nexturl: json["nexturl"],
tableMenuList: List<TableMenuList>.from(
json["table_menu_list"].map((x) => TableMenuList.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"restaurant_id": restaurantId,
"restaurant_name": restaurantName,
"restaurant_image": restaurantImage,
"table_id": tableId,
"table_name": tableName,
"branch_name": branchName,
"nexturl": nexturl,
"table_menu_list":
List<dynamic>.from(tableMenuList.map((x) => x.toJson())),
};
}
class TableMenuList {
String menuCategory;
String menuCategoryId;
String menuCategoryImage;
String nexturl;
List<CategoryDish> categoryDishes;
TableMenuList({
this.menuCategory,
this.menuCategoryId,
this.menuCategoryImage,
this.nexturl,
this.categoryDishes,
});
factory TableMenuList.fromJson(Map<String, dynamic> json) => TableMenuList(
menuCategory: json["menu_category"],
menuCategoryId: json["menu_category_id"],
menuCategoryImage: json["menu_category_image"],
nexturl: json["nexturl"],
categoryDishes: List<CategoryDish>.from(
json["category_dishes"].map((x) => CategoryDish.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"menu_category": menuCategory,
"menu_category_id": menuCategoryId,
"menu_category_image": menuCategoryImage,
"nexturl": nexturl,
"category_dishes":
List<dynamic>.from(categoryDishes.map((x) => x.toJson())),
};
}
class AddonCat {
String addonCategory;
String addonCategoryId;
int addonSelection;
String nexturl;
List<CategoryDish> addons;
AddonCat({
this.addonCategory,
this.addonCategoryId,
this.addonSelection,
this.nexturl,
this.addons,
});
factory AddonCat.fromJson(Map<String, dynamic> json) => AddonCat(
addonCategory: json["addon_category"],
addonCategoryId: json["addon_category_id"],
addonSelection: json["addon_selection"],
nexturl: json["nexturl"],
addons: List<CategoryDish>.from(
json["addons"].map((x) => CategoryDish.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"addon_category": addonCategory,
"addon_category_id": addonCategoryId,
"addon_selection": addonSelection,
"nexturl": nexturl,
"addons": List<dynamic>.from(addons.map((x) => x.toJson())),
};
}
class CategoryDish {
String dishId;
String dishName;
double dishPrice;
String dishImage;
DishCurrency dishCurrency;
int dishCalories;
String dishDescription;
bool dishAvailability;
int dishType;
String nexturl;
List<AddonCat> addonCat;
CategoryDish({
this.dishId,
this.dishName,
this.dishPrice,
this.dishImage,
this.dishCurrency,
this.dishCalories,
this.dishDescription,
this.dishAvailability,
this.dishType,
this.nexturl,
this.addonCat,
});
factory CategoryDish.fromJson(Map<String, dynamic> json) => CategoryDish(
dishId: json["dish_id"],
dishName: json["dish_name"],
dishPrice: json["dish_price"].toDouble(),
dishImage: json["dish_image"],
dishCurrency: dishCurrencyValues.map[json["dish_currency"]],
dishCalories: json["dish_calories"],
dishDescription: json["dish_description"],
dishAvailability: json["dish_Availability"],
dishType: json["dish_Type"],
nexturl: json["nexturl"] == null ? null : json["nexturl"],
addonCat: json["addonCat"] == null
? null
: List<AddonCat>.from(
json["addonCat"].map((x) => AddonCat.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"dish_id": dishId,
"dish_name": dishName,
"dish_price": dishPrice,
"dish_image": dishImage,
"dish_currency": dishCurrencyValues.reverse[dishCurrency],
"dish_calories": dishCalories,
"dish_description": dishDescription,
"dish_Availability": dishAvailability,
"dish_Type": dishType,
"nexturl": nexturl == null ? null : nexturl,
"addonCat": addonCat == null
? null
: List<dynamic>.from(addonCat.map((x) => x.toJson())),
};
}
enum DishCurrency { SAR }
final dishCurrencyValues = EnumValues({"SAR": DishCurrency.SAR});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
I personally use this one for generating dart classes from JSON https://javiercbk.github.io/json_to_dart/
From my experience most of these automatic class builders are flawed to some extent and it is good practice to go over the generated dart manually. Or try your luck and walk the stack trace to see where parsing failed (usually when handling int and double from what I've seen).
Anyhow back to your problem, from looking at your code I see you are misusing indexes and generally having problems with json data structure:
title: Text(welcome[index]
.tableMenuList[index]
.categoryDishes[index]
.dishName),
The code above can easily throw "RangeError (index): Invalid value: Not in range..." (example if welcome[ 2 ] has only 1 tableMenuList). Even if all those arrays above are somehow the same length you would still not get the expected result.. The list would end up showing you 1st meal from the 1st menu list and 1st category dish, then next one would be 2nd meal from the 2nd menu and the 2nd restaurant.
Also because of the same reason as above the following code isn't enough:
itemCount: myData == null ? 0 : myData.length,
You need to have an itemCount for each of those lists you are using.
I've modified your code to work with the given JSON and changed a few things, in the end it looks like this.
I'm posting my source bellow, hopefully it will make things clearer for you:
pubspec.yaml
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
http: any
welcome_model.dart
class Welcome {
String restaurantId;
String restaurantName;
String restaurantImage;
String tableId;
String tableName;
String branchName;
String nexturl;
List<TableMenuList> tableMenuList;
Welcome(
{this.restaurantId,
this.restaurantName,
this.restaurantImage,
this.tableId,
this.tableName,
this.branchName,
this.nexturl,
this.tableMenuList});
Welcome.fromJson(Map<String, dynamic> json) {
restaurantId = json['restaurant_id'];
restaurantName = json['restaurant_name'];
restaurantImage = json['restaurant_image'];
tableId = json['table_id'];
tableName = json['table_name'];
branchName = json['branch_name'];
nexturl = json['nexturl'];
if (json['table_menu_list'] != null) {
tableMenuList = new List<TableMenuList>();
json['table_menu_list'].forEach((v) {
tableMenuList.add(new TableMenuList.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['restaurant_id'] = this.restaurantId;
data['restaurant_name'] = this.restaurantName;
data['restaurant_image'] = this.restaurantImage;
data['table_id'] = this.tableId;
data['table_name'] = this.tableName;
data['branch_name'] = this.branchName;
data['nexturl'] = this.nexturl;
if (this.tableMenuList != null) {
data['table_menu_list'] =
this.tableMenuList.map((v) => v.toJson()).toList();
}
return data;
}
}
class TableMenuList {
String menuCategory;
String menuCategoryId;
String menuCategoryImage;
String nexturl;
List<CategoryDishes> categoryDishes;
TableMenuList(
{this.menuCategory,
this.menuCategoryId,
this.menuCategoryImage,
this.nexturl,
this.categoryDishes});
TableMenuList.fromJson(Map<String, dynamic> json) {
menuCategory = json['menu_category'];
menuCategoryId = json['menu_category_id'];
menuCategoryImage = json['menu_category_image'];
nexturl = json['nexturl'];
if (json['category_dishes'] != null) {
categoryDishes = new List<CategoryDishes>();
json['category_dishes'].forEach((v) {
categoryDishes.add(new CategoryDishes.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['menu_category'] = this.menuCategory;
data['menu_category_id'] = this.menuCategoryId;
data['menu_category_image'] = this.menuCategoryImage;
data['nexturl'] = this.nexturl;
if (this.categoryDishes != null) {
data['category_dishes'] =
this.categoryDishes.map((v) => v.toJson()).toList();
}
return data;
}
}
class CategoryDishes {
String dishId;
String dishName;
double dishPrice;
String dishImage;
String dishCurrency;
double dishCalories;
String dishDescription;
bool dishAvailability;
int dishType;
String nexturl;
List<AddonCat> addonCat;
CategoryDishes(
{this.dishId,
this.dishName,
this.dishPrice,
this.dishImage,
this.dishCurrency,
this.dishCalories,
this.dishDescription,
this.dishAvailability,
this.dishType,
this.nexturl,
this.addonCat});
CategoryDishes.fromJson(Map<String, dynamic> json) {
dishId = json['dish_id'];
dishName = json['dish_name'];
dishPrice = json['dish_price'];
dishImage = json['dish_image'];
dishCurrency = json['dish_currency'];
dishCalories = json['dish_calories'];
dishDescription = json['dish_description'];
dishAvailability = json['dish_Availability'];
dishType = json['dish_Type'];
nexturl = json['nexturl'];
if (json['addonCat'] != null) {
addonCat = new List<AddonCat>();
json['addonCat'].forEach((v) {
addonCat.add(new AddonCat.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['dish_id'] = this.dishId;
data['dish_name'] = this.dishName;
data['dish_price'] = this.dishPrice;
data['dish_image'] = this.dishImage;
data['dish_currency'] = this.dishCurrency;
data['dish_calories'] = this.dishCalories;
data['dish_description'] = this.dishDescription;
data['dish_Availability'] = this.dishAvailability;
data['dish_Type'] = this.dishType;
data['nexturl'] = this.nexturl;
if (this.addonCat != null) {
data['addonCat'] = this.addonCat.map((v) => v.toJson()).toList();
}
return data;
}
}
class AddonCat {
String addonCategory;
String addonCategoryId;
int addonSelection;
String nexturl;
List<Addons> addons;
AddonCat(
{this.addonCategory,
this.addonCategoryId,
this.addonSelection,
this.nexturl,
this.addons});
AddonCat.fromJson(Map<String, dynamic> json) {
addonCategory = json['addon_category'];
addonCategoryId = json['addon_category_id'];
addonSelection = json['addon_selection'];
nexturl = json['nexturl'];
if (json['addons'] != null) {
addons = new List<Addons>();
json['addons'].forEach((v) {
addons.add(new Addons.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['addon_category'] = this.addonCategory;
data['addon_category_id'] = this.addonCategoryId;
data['addon_selection'] = this.addonSelection;
data['nexturl'] = this.nexturl;
if (this.addons != null) {
data['addons'] = this.addons.map((v) => v.toJson()).toList();
}
return data;
}
}
class Addons {
String dishId;
String dishName;
double dishPrice;
String dishImage;
String dishCurrency;
double dishCalories;
String dishDescription;
bool dishAvailability;
int dishType;
Addons(
{this.dishId,
this.dishName,
this.dishPrice,
this.dishImage,
this.dishCurrency,
this.dishCalories,
this.dishDescription,
this.dishAvailability,
this.dishType});
Addons.fromJson(Map<String, dynamic> json) {
dishId = json['dish_id'];
dishName = json['dish_name'];
dishPrice = json['dish_price'];
dishImage = json['dish_image'];
dishCurrency = json['dish_currency'];
dishCalories = json['dish_calories'];
dishDescription = json['dish_description'];
dishAvailability = json['dish_Availability'];
dishType = json['dish_Type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['dish_id'] = this.dishId;
data['dish_name'] = this.dishName;
data['dish_price'] = this.dishPrice;
data['dish_image'] = this.dishImage;
data['dish_currency'] = this.dishCurrency;
data['dish_calories'] = this.dishCalories;
data['dish_description'] = this.dishDescription;
data['dish_Availability'] = this.dishAvailability;
data['dish_Type'] = this.dishType;
return data;
}
}
welcome_page.dart
import 'package:flutter/material.dart';
import 'welcome_model.dart';
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
class WelcomePage extends StatefulWidget {
#override
_WelcomePageState createState() => new _WelcomePageState();
}
class _WelcomePageState extends State<WelcomePage> {
List<Welcome> welcomeList;
bool isLoading = true;
int selectedRestaurantIndex = 0;
String titleString = "Restaurant";
#override
void initState() {
super.initState();
_fetchData();
}
#override
void setState(fn) {
if(mounted){
super.setState(fn);
}
}
#override
void dispose() {
super.dispose();
}
_fetchData() async{
setState(() {
isLoading = true;
});
// String url = Uri.encodeFull("http://www.mocky.io/v2/5dfccffc310000efc8d2c1ad"); // original json has only one restaurant
// the one bellow has 3 restaurants,
// 1st one was left untouched,
// 2nd one (Steak house) has only "From The Barnyard" and "Fast Food" menu types
// 3rd one (Bistro cafe) has only "Fresh From The Sea" and "Fast Food" menu types
String url = Uri.encodeFull("http://www.mocky.io/v2/5e4aa68c2f0000690097d3f6");
var parsedJson;
try {
http.Response response = await http.get(url).
timeout(Duration(seconds: 10));
if (response.statusCode == 200) {
if (response.bodyBytes != null) {
parsedJson = json.decode(utf8.decode(response.bodyBytes));
}
} else {
print('RESPONSE CODE != 200 !');
}
} on TimeoutException catch (e) {
print('Error: $e');
} on SocketException catch (e) {
print('Error: $e');
} on Error catch (e) {
print('Error: $e');
}
if(parsedJson!=null){
if(parsedJson.length>0){
welcomeList = new List<Welcome>();
for(int i=0; i<parsedJson.length; i++) {
try {
welcomeList.add(Welcome.fromJson(parsedJson[i]));
} catch (e, s){
print('Eroor parsing from JSON! For # $i');
print('Error: $e');
print('Stacktrace: $s');
}
}
if(welcomeList[0]!=null && welcomeList[0].restaurantName!=null) {
titleString = welcomeList[0].restaurantName;
}
}
}
setState(() {
isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
iconTheme: IconThemeData(
color: Colors.white,
),
title: Text(titleString),
centerTitle: true,
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text("Select a restaurant", style: TextStyle(color: Colors.white, fontSize: 28),textAlign: TextAlign.center,
),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
),
),
(welcomeList!=null && welcomeList.length>0) ?
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: welcomeList.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
setState(() {
selectedRestaurantIndex = index;
titleString = welcomeList[index].restaurantName.toString();
});
Navigator.pop(context);
},
padding: EdgeInsets.all(12),
child: Text(welcomeList[index].restaurantName.toString()),
)
);
;}
)
: Text("No restaurants loaded...")
]
)
),
body: (isLoading)
? Center(child: CircularProgressIndicator(),)
: Container(
child: Center(
child: ListView.builder(
itemBuilder: (BuildContext context, int index1) {
return Card(
child: ListTile(
subtitle: Text(welcomeList[selectedRestaurantIndex].tableMenuList[index1].menuCategory.toString()),
title: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemBuilder: (BuildContext context, int index2) {
return Card(
child: ListTile(
title: Text(welcomeList[selectedRestaurantIndex].tableMenuList[index1].categoryDishes[index2].dishName.toString()),
));
},
itemCount: (welcomeList[selectedRestaurantIndex].tableMenuList[index1] == null || welcomeList[selectedRestaurantIndex].tableMenuList[index1].categoryDishes == null) ? 0 : (welcomeList[selectedRestaurantIndex].tableMenuList[index1].categoryDishes.length) ,)
)
);
},
itemCount: (welcomeList == null || welcomeList[selectedRestaurantIndex] == null || welcomeList[selectedRestaurantIndex].tableMenuList == null) ? 0 : (welcomeList[selectedRestaurantIndex].tableMenuList.length) ,
)
),
),
);
}
}
JSON with 3 restaurants here or here.

How to authenticate the websocket in flutter

I am using Traccar but could not use websocket in Flutter as it is not providing any data.
I think websocket requires authentication or tokens to get the data.
class _HomeState extends State<Home> {
IOWebSocketChannel channel = IOWebSocketChannel.connect("ws://167.172.215.197:8082/api/socket");
#override
Widget build(BuildContext context) {
print(channel);
return new Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text('Map'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// details(),
StreamBuilder(
stream: channel.stream,
builder: (context, snapshot) {
print(snapshot);
return Padding(
padding: const EdgeInsets.symmetric(vertical: 24.0),
child: Container(
child:
Column(
children: <Widget>[
Text(snapshot.hasData ? '${snapshot.data.positions}' : 'No Data'),
],
),
),
);
},
)
],
),
);
}
}
I want to receive the data from the server using websocket in flutter.
yes you need to authenticate and use some variables, for example:
String _cookie;
String _email = "your_email";
String _password = "your_password" ;
final _dio = Dio();
String _cookie;
String serverUrl = "your_server_ip";
StreamSubscription<dynamic> _rawPosSub;
final _devicesMap = <int, Device>{};
final _positions = StreamController<Device>.broadcast();
Future<void> _getConnection({String protocol = "http", String email, String password}) async {
final addr = "$protocol://$serverUrl/api/session";
Map<String, String> body = {
'email' : '$email',
'password': '$password',
};
final response = await Dio().post(addr, data: body,
options: new Options(contentType:"application/x-www-form-urlencoded"));
_cookie = response.headers["set-cookie"][0];
print(_cookie);
}
Next, you should need to create a Device Class (Don't forget to change the project name in the import line of utils)
import 'package:geopoint/geopoint.dart';
import 'package:your_project/utils/utils.dart';
/// A class representing a device
class Device {
/// Main constructor
Device(
{this.id,
this.uniqueId,
this.groupId,
this.name,
this.position,
this.batteryLevel,
this.keepAlive = 1,
this.isActive,
this.isDisabled,
this.properties = const <String, dynamic>{}});
/// The device database id
final int id;
/// The on device unique id
String uniqueId;
/// The group of the device
int groupId;
/// The device name
String name;
/// The device position
DevicePosition position;
/// The device battery level
double batteryLevel;
/// Minutes a device is considered alive
int keepAlive;
/// The device can be disabled
bool isDisabled;
/// false if the device has never updated one position
bool isActive;
/// Extra properties for the device
Map<String, dynamic> properties;
/// Is the device online
bool get isAlive => _isDeviceAlive();
/// Create a device from json data
Device.fromPosition(Map<String, dynamic> data,
{String timeZoneOffset = "0", int keepAlive = 1})
: this.keepAlive = keepAlive,
this.id = int.parse(data["deviceId"].toString()),
this.position =
DevicePosition.fromJson(data, timeZoneOffset: timeZoneOffset),
this.batteryLevel =
double.parse(data["attributes"]["batteryLevel"].toString());
bool _isDeviceAlive() {
if (position == null) {
return false;
}
final now = DateTime.now();
final dateAlive = now.subtract(Duration(minutes: keepAlive));
bool isAlive = false;
if (position.date.isAfter(dateAlive)) {
isAlive = true;
}
return isAlive;
}
/// Print a description of the device
void describe() {
print("Device:");
print(" - id : $id");
print(" - uniqueId : $uniqueId");
print(" - name : $name");
print(" - batteryLevel: $batteryLevel");
print(" - position : $position");
}
#override
String toString() {
String _name = "$uniqueId";
if (name != null) {
_name = name;
}
String res;
if (position != null) {
res = "$_name: $position";
} else {
res = "$_name";
}
return res;
}
}
/// A class to handle a device position
class DevicePosition {
/// The position database id
final int id;
/// The geo data
final GeoPoint geoPoint;
/// The distance since previous point
final double distance;
/// The total distance for the device
final double totalDistance;
/// The address of the device position
final String address;
/// The date of the position
DateTime date;
/// Create a position from json
DevicePosition.fromJson(Map<String, dynamic> data,
{String timeZoneOffset = "0"})
: this.id = int.parse(data["id"].toString()),
this.geoPoint = GeoPoint(
name: data["id"].toString(),
latitude: double.parse(data["latitude"].toString()),
longitude: double.parse(data["longitude"].toString()),
speed: double.parse(data["speed"].toString()),
accuracy: double.parse(data["accuracy"].toString()),
altitude: double.parse(data["altitude"].toString())),
this.distance = double.parse(data["attributes"]["distance"].toString()),
this.totalDistance =
double.parse(data["attributes"]["totalDistance"].toString()),
this.address = data["address"].toString() {
this.date = dateFromUtcOffset(data["fixTime"].toString(), timeZoneOffset);
}
#override
String toString() {
return "$date : ${geoPoint.latitude}, ${geoPoint.longitude}";
}
}
Also you should use a utils method
/// parse a date
DateTime dateFromUtcOffset(String dateStr, String timeZoneOffset) {
DateTime d = DateTime.parse(dateStr);
if (timeZoneOffset.startsWith("+")) {
final of = int.parse(timeZoneOffset.replaceFirst("+", ""));
d = d.add(Duration(hours: of));
} else if (timeZoneOffset.startsWith("-")) {
final of = int.parse(timeZoneOffset.replaceFirst("-", ""));
d = d.subtract(Duration(hours: of));
}
return d;
}
Finally you should need the following methods to listen positions:
/// Get the device positions
Future<Stream<Device>> positions() async {
final posStream =
await _positionsStream(serverUrl: serverUrl, email: _email, password: _password);
_rawPosSub = posStream.listen((dynamic data) {
print("DATA $data");
final dataMap = json.jsonDecode(data.toString()) as Map<String, dynamic>;
if (dataMap.containsKey("positions")) {
DevicePosition pos;
for (final posMap in dataMap["positions"]) {
//print("POS MAP $posMap");
pos = DevicePosition.fromJson(posMap as Map<String, dynamic>);
final id = posMap["deviceId"] as int;
Device device;
if (_devicesMap.containsKey(id)) {
device = _devicesMap[id];
} else {
device = Device.fromPosition(posMap as Map<String, dynamic>,
keepAlive: 1);
}
device.position = pos;
_devicesMap[id] = device;
_positions.sink.add(device);
}
} else {
for (final d in dataMap["devices"]) {
if (!_devicesMap.containsKey(d["id"])) {
final id = int.parse(d["id"].toString());
d["name"] ??= d["id"].toString();
final device = Device(id: id, name: d["name"].toString());
_devicesMap[id] = device;
//print(" - ${device.name}");
}
}
}
});
return _positions.stream;
}
Future<Stream<dynamic>> _positionsStream(
{String serverUrl, String email, String password, String protocol = "http"}) async {
if (_cookie == null) {
await _getConnection(email: _email, password: _password);
}
final channel = IOWebSocketChannel.connect("ws://$serverUrl/api/socket",
headers: <String, dynamic>{"Cookie": _cookie});
return channel.stream;
}
When you finish, you can call
_init() async {
_getConnection(email: _email, password: _password);
final pos = await positions();
print("Listening for position updates");
pos.listen((device) {
print("POSITION UPDATE: $device");
print("${device.id}: ${device.position.geoPoint.latitude} / " +
"${device.position.geoPoint.longitude}");
});
}
Also I use these dependences and flutter version 1.17.0 stable:
dio: ^3.0.9
web_socket_channel:
geopoint: ^0.7.1
Note: I use code from traccar_client 0.1.0 and modify it to access from email and password, but if you need to use the token, you can follow the example from
https://github.com/synw/traccar_client. The credits are to them. :)