Flutter does not output all the results during a post request - arrays

Flutter does not output all the results during a post request. Out of about 260 comes to the list, 113 are saved.
...............................................................................................................................................................................................................
Future<List<NewChatModel>> getAllChats({#required String userId}) async {
final response = await http.post(
Uri.parse(URL),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, int>{
'first_user_id': int.parse(userId),
}),
);
if (response.statusCode == 200) {
List<NewChatModel> returnList = [];
for (var i in jsonDecode(response.body)) {
returnList.add(NewChatModel.fromJson(i));
}
print(returnList.length);
return returnList;
} else {
return null;
}
}
class NewChatModel {
String id;
String chatId;
String messageId;
String message;
String messageDate;
String schoolId;
String fullName;
String phone;
String email;
String urlProfileImage;
String birthday;
String roleId;
String lastActivity;
String isOnline;
NewChatModel(
{this.id,
this.chatId,
this.messageId,
this.message,
this.messageDate,
this.schoolId,
this.fullName,
this.phone,
this.email,
this.urlProfileImage,
this.birthday,
this.roleId,
this.lastActivity,
this.isOnline});
factory NewChatModel.fromJson(dynamic json) {
return NewChatModel(
id: json['id'].toString(),
chatId: json['chat_id'].toString(),
messageId: json['message_id'].toString(),
message: json['message'].toString(),
messageDate: json['message_date'].toString(),
schoolId: json['school_id'].toString(),
fullName: json['full_name'].toString(),
phone: json['phone'].toString(),
email: json['email'].toString(),
urlProfileImage: json['urlProfileImage'].toString(),
birthday: json['birthday'].toString(),
roleId: json['role_id'].toString(),
lastActivity: json['last_activity'].toString(),
isOnline: json['is_online'].toString(),
);
}
}
Edit: added NewChatModel code
But I don`t think that its help solve problem
I think problem in String limit, idk

If at all it helps you, I have a list of chat conversations in my app, too. I collect them with a Stream and display them with a StreamBuilder(). This is a very resource efficient way to do it, without the need to actually collect all the conversations at once! The StreamBuilder() widget makes sure it collects only the conversations that are currently visible on the screen (plus some).
This is what it looks like:
import 'package:my_giggz/firebase_labels.dart';
import 'package:my_giggz/my_firebase.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class MyMessagesScreen extends StatefulWidget {
#override
_MyMessagesScreenState createState() {
return _MyMessagesScreenState();
}
}
class _MyMessagesScreenState extends State<MyMessagesScreen> {
String myUid = MyFirebase.authObject.currentUser!.uid;
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<QuerySnapshot>(
// Stream of all the conversations in the database that contain my uid:
stream: MyFirebase.storeObject.collection(kCollectionConversations).where(kFieldParticipantsArray, arrayContains: myUid).orderBy(kFieldLastTimeStamp, descending: true).snapshots(),
builder: (context, asyncSnapshot) {
List<Widget> convCards = [];
QuerySnapshot? foundConversations = asyncSnapshot.data;
if (foundConversations != null) {
//It always wants to be null at first, and then I get errors for calling on null.
for (QueryDocumentSnapshot conv in foundConversations.docs) {
Map<String, dynamic> convData = conv.data() as Map<String, dynamic>;
convCards.add(
ConvCard(convData) // A homemade widget that takes a Map argument to display some data from the conversation
);
// i++;
}
} else {
// For as long as the found conversations are null, a spinner will be shown:
return Center(child: CircularProgressIndicator());
}
// This part will only be reached if conversations were found:
return ListView.builder(
padding: EdgeInsets.all(0),
itemCount: convCards.length,
itemBuilder: (context, index) {
return convCards[index];
},
);
},
),
);
}
}
If you have any questions on that, I'm happy to answer.

I do not know why this is so, but here is the answer to my question :)
For some reason, he doesn't want to show the entire length of the list, but he filled it out absolutely correctly)

Related

Parsing a JSON to convert some parameters into HEX/String

I have the following problem, I'm new in Dart, and I'm using a Future to construct a list view from a JSON response of an API, once I do this request, I receive the following response:
REQUEST:
Future<List<Job>> _fetchJobs() async {
final response = await http.get(
Uri.parse('http://10.10.10.254/httpapi.asp?command=wlanGetApListEx'));
if (response.statusCode == 200) {
final List jsonResponse = json.decode(response.body)['aplist'] as List;
print(jsonResponse);
return jsonResponse.map((job) => new Job.fromJson(job)).toList();
} else {
throw Exception('Failed to load jobs from API');
}
}
[
{
"ssid":444A446F626C65615F322E34,
"bssid":"80":"3f":"5d":"ed":"cd":f9,
"rssi":42,
"channel":8,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
},
{
"ssid":426172696369632D322E3447,
"bssid":"b0":"76":"1b":"f4":"55":80,
"rssi":18,
"channel":1,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
},
{
"ssid":46616D696C69615F65737061727A61,
"bssid":"60":"32":"b1":"71":"ce":46,
"rssi":0,
"channel":5,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
},
{
"ssid":43617361204C756369616E61,
"bssid":"20":"ab":"48":"86":"17":58,
"rssi":0,
"channel":11,
"auth":WPA2PSK,
"encry":"AES",
"extch":0
}
]
As you can see, the SSID values are in HEX and I need it in UTF-16 or UTF-8
I was trying to implement the hex package, but I can not find how to implement it on a JSON array like this.
The hex codex is in the convert package (not to be confused with the dart built in convert library).
If you need to convert the string you have to its ascii/utf8 form use both convert libraries like this:
import 'dart:convert';
import 'package:convert/convert.dart';
void main() {
final h = '444A446F626C65615F322E34';
final u = utf8.decode(hex.decode(h));
print(u); // prints DJDoblea_2.4
}
The more troubling issue seems to be that the data excerpt you provide is not valid JSON, so you cannot, of course, decode it with json.decode.
Try the following code:
import 'dart:convert';
import 'package:convert/convert.dart';
class Job {
Job({required this.ssid, required this.auth, required this.encry});
final String ssid;
final String auth;
final String encry;
factory Job.fromJson(Map<String, dynamic> json) {
return Job(
ssid: utf8.decode(hex.decode(json['ssid'])),
auth: json['auth'],
encry: json['encry'],
);
}
Map<String, dynamic> toMap() {
return {
'ssid': ssid,
'auth': auth,
'encry': encry,
};
}
}
final List<Map<String, dynamic>> jsonResponse = (json.decode(response.body)['aplist'] as List).map((e) => Job.fromJson(e)).map((e) => e.toMap()).toList();

Flutter firebase, how to retrive user data and have it on the map or a list

I saw many examples on internet, but in each case, the data is returning on a listview. I don't want to print in a listview. I want to use data in the app.
This is the way I am addind data on firebase. (I am using a class Info).
void infouser(context) async {
final db = FirebaseFirestore.instance;
final info = Info(yourname, animaName, yourmail);
final uid = await Provider.of(context).auth.getCurrentUID();
await db.collection("userData").doc(uid).collection("info").add(info.toJson());
}
I also tried with set,
createInfo(context) async {
final uid = await Provider.of(context).auth.getCurrentUID();
DocumentReference documentReference =
await FirebaseFirestore.instance.collection('Animal').doc(uid);
Map<String, dynamic> todos = {
'name': yourname,
'animalname' :animalName,
'email' : yourmail,
};
documentReference.set(todos).whenComplete(() {
print( yourname, animalName, yourmail
);
});
}
In both case, I was only able to print data on a Listview. But that is not what I want. I want to have data on a list or a map to be able to use it elsewhere in the app.
Please, I if you have a link(or give me a example of code) where I can see example, it will be appreciate.
thank you.
This is the example of retrieving data as map from firestore:
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName(this.documentId);
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data();
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return Text("loading");
},
);
}
}
I advise to use https://firebase.flutter.dev/docs/firestore/usage/? documentation when working with Firebase from flutter

JSON http.get return áá flutter

I am trying to retrieve a JSON from a URL link. The JSON data consist of both English and Burmese language. However, when I retrieve the data, the app shows a bunch of Burmese words converted into "áá". Any solutions?
class _GetJsonResultState extends State<GetJsonResult> {
#override
Widget build(BuildContext context) {
var jsonFileName = "assets/resultlist/resultlist.json";
fetchData() async {
final response =
await http.get('https://jsonkeeper.com/b/47QP');
if (response.statusCode == 200) {
return(response.body);
}
}
return FutureBuilder(
future: fetchData(),
builder: (context, snapshot) {
List myData = json.decode(snapshot.data.toString());
if (myData == null) {
return Scaffold(
body: Center(
// Loads upon null
child: CircularProgressIndicator(),
),
);
} else {
return Home(myData: myData);
}
},
);
}
}
This is what I'm supposed to get
Change your fetchData() function as below
fetchData() async {
final response = await http.get('https://jsonkeeper.com/b/47QP',
headers: {"charset": "utf-8", "Accept-Charset": "utf-8"});
if (response.statusCode == 200) {
return (utf8.decode(response.bodyBytes));
}
}
Its a decoding issue. Just to clarify what is happening in background
The Dart http API defines (as mentioned below) two ways of interacting with the response data:
body → String
The body of the response as a string. This is converted from bodyBytes using the charset parameter of the Content-Type header field, if available. If it's unavailable or if the encoding name is unknown, latin1 is used by default, as per RFC 2616.
bodyBytes → Uint8List
The bytes comprising the body of this response.
More details at https://github.com/dart-lang/http/issues/175#issuecomment-415721621
So in such cases where you know encoding before hand and think its going to mess use request encoding and a decode from byte
fetchData() async {
final response = await http.get('https://jsonkeeper.com/b/47QP',
headers: {"charset": "utf-8", "Accept-Charset": "utf-8"});
if (response.statusCode == 200) {
return (utf8.decode(response.bodyBytes));
}
}

Encoding / decoding complex Json in Flutter

I am going to use a real json. First of all, I should run the project that is written in Flask, then use the local host to achieve data.
Here is the real Json I`m using
{
"devices":[
{
"device_desc":"cooler",
"device_title":"cooler",
"functions":[
{
"device_id":1,
"function_desc":"pomp",
"function_title":"pomp",
"status":1
},
{
"device_id":1,
"function_desc":"less",
"function_title":"less",
"status":1
},
{
"device_id":1,
"function_desc":"up",
"function_title":"up",
"status":1
}
],
"image_path":"fdfdfsf",
"status_id":1,
"statuss":{
"status_desc":"device is on",
"status_title":"on"
}
},
{
"device_desc":"panke",
"device_title":"panke",
"functions":[
{
"device_id":2,
"function_desc":"less",
"function_title":"pomp",
"status":2
},
{
"device_id":2,
"function_desc":"less",
"function_title":"less",
"status":2
}
],
"image_path":"vfx",
"status_id":2,
"statuss":{
"status_desc":"device is off",
"status_title":"off"
}
}
]
}
This is my code:
these are data models for defining json properties:
class Base{
//the type of our object is the array
List<Device> _devices;
Base(this._devices);
List<Device> get devices => _devices;
set devices(List<Device> value) {
_devices = value;
}
}
class Device {
String _device_desc,_device_title,_image_path;
int _status_id;
List<function> _functions;
List<Status> _statuss ;
Device(this._device_desc, this._device_title, this._image_path,
this._status_id, this._functions, this._statuss);
List<Status> get statuss => _statuss;
set statuss(List<Status> value) {
_statuss = value;
}
List<function> get functions => _functions;
set functions(List<function> value) {
_functions = value;
}
int get status_id => _status_id;
set status_id(int value) {
_status_id = value;
}
get image_path => _image_path;
set image_path(value) {
_image_path = value;
}
get device_title => _device_title;
set device_title(value) {
_device_title = value;
}
String get device_desc => _device_desc;
set device_desc(String value) {
_device_desc = value;
}
}
class Status {
String _status_desc, _status_title;
Status(this._status_desc, this._status_title);
get status_title => _status_title;
set status_title(value) {
_status_title = value;
}
String get status_desc => _status_desc;
set status_desc(String value) {
_status_desc = value;
}}
class function {
String _function_desc, _function_title;
int _device_id, _status;
function(this._function_desc, this._function_title, this._device_id,
this._status);
get status => _status;
set status(value) {
_status = value;
}
int get device_id => _device_id;
set device_id(int value) {
_device_id = value;
}
get function_title => _function_title;
set function_title(value) {
_function_title = value;
}
String get function_desc => _function_desc;
set function_desc(String value) {
_function_desc = value;
}}
and this is the stateful class :
class MyHomePage extends StatefulWidget {
var title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<Base> _getBase() async {
var data = await http.get(Uri.encodeFull("http://192.168.1.111:5000/mobile-home"));
var jsonData = json.decode(data.body);
Base base = Base(jsonData);
return Base(jsonData[0]);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Container(
child: FutureBuilder(
future: _getBase(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text("Loading..."),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.devices.length,
itemBuilder: (BuildContext context, int index) {
snapshot.data.devices.map<Widget>((devices){
return ListTile(
subtitle: Text(devices[index].device_desc.toString()),
title: Text(devices[index].device_title),
/*leading: CircleAvatar(
// ignore: argument_type_not_assignable
backgroundImage: NetworkImage(snapshot.data[index].thumbnailUrl),
)*/
);
}
);
},
);
}
},
),
),
);
}
}
I got an error when while debugging:
"type 'List<dynamic>' is not a subtype of type 'List<Device>'"
I can not get the data from json.
There was no question in your question, but I assume the question is:
My Json code is not working - How do I efficiently parse and encode complex json objects in my
flutter program.
For complex JSON you may want to consider using code generation to reduce the boiler plate you have to write. The flutter page has a good example using JsonSerializable. Here the basic instructions for your example:
Add dependencies to pubspec.yaml and run flutter pub get in the command line:
dependencies:
json_annotation: ^1.2.0
dev_dependencies:
build_runner: ^1.0.0
json_serializable: ^1.5.1
Create the basic Object model (similar to what you have done). Except for the following differences:
You don't have a List of Status for the field statuss, but a single Status object.
Don't use private fields.
To enable json boiler plate code generation do the following three steps:
add the json-annotations to each class,
add a factory .fromJson method on each class and
add a .toJson method on each class:
#JsonSerializable()
class Base {
List<Device> devices;
Base({this.devices});
factory Base.fromJson(Map<String, dynamic> json) => _$BaseFromJson(json);
Map<String, dynamic> toJson() => _$BaseToJson(this);
}
#JsonSerializable()
class Device {
String device_desc,device_title,image_path;
int status_id;
List<function> functions;
Status statuss ;
Device(this.device_desc, this.device_title, this.image_path,
this.status_id, this.functions, this.statuss);
factory Device.fromJson(Map<String, dynamic> json) => _$DeviceFromJson(json);
Map<String, dynamic> toJson() => _$DeviceToJson(this);
}
#JsonSerializable()
class Status {
String status_desc, status_title;
Status(this.status_desc, this.status_title);
factory Status.fromJson(Map<String, dynamic> json) => _$StatusFromJson(json);
Map<String, dynamic> toJson() => _$StatusToJson(this);
}
#JsonSerializable()
class function {
String function_desc, function_title;
int device_id, status;
function(this.function_desc, this.function_title, this.device_id,
this.status);
factory function.fromJson(Map<String, dynamic> json) => _$functionFromJson(json);
Map<String, dynamic> toJson() => _$functionToJson(this);
}
Run the command line to start code generation in the project root folder:
flutter packages pub run build_runner watch
Now an additional source file appears with your generated boiler plate code. Add this file to your own source file using the part keyword, for example if your source file is main.dart add the following line:
part 'main.g.dart';
And you are done - This is all you need to test your encoding / decoding. For example with the following code:
import 'dart:convert';
void main() => (){
var jsonExample = '{"devices": [{"device_desc": "cooler", "device_title": "cooler", "functions": [{"device_id": 1, "function_desc": "pomp", "function_title": "pomp", "status": 1}, {"device_id": 1, "function_desc": "less", "function_title": "less", "status": 1}, {"device_id": 1, "function_desc": "up", "function_title": "up", "status": 1}], "image_path": "fdfdfsf", "status_id": 1, "statuss": {"status_desc": "device is on", "status_title": "on"}}, {"device_desc": "panke", "device_title": "panke", "functions": [{"device_id": 2, "function_desc": "less", "function_title": "pomp", "status": 2}, {"device_id": 2, "function_desc": "less", "function_title": "less", "status": 2}], "image_path": "vfx", "status_id": 2, "statuss": {"status_desc": "device is off", "status_title": "off"}}]}';
Map base_example = json.decode(jsonExample);
Base base_example_parsed = Base.fromJson(base_example);
var numberDevices = base_example_parsed.devices.length;
var numberFuncs = base_example_parsed.devices[0].functions.length;
print('$base_example_parsed has $numberDevices devices and the first device has $numberFuncs functions');
var base_example_encoded_again = json.encode(base_example_parsed);
print('$base_example_encoded_again');
};
For more information please refer to:
1. the official example.
2. this blog.
There's a very good article about how to parse complex JSON in Flutter. Here's a quick summary...
Simple Stuff:
{
"id":"487349",
"name":"Pooja Bhaumik",
"score" : 1000
}
becomes...
class Student{
String studentId;
String studentName;
int studentScores;
Student({
this.studentId,
this.studentName,
this.studentScores
});
factory Student.fromJson(Map<String, dynamic> parsedJson){
return Student(
studentId: parsedJson['id'],
studentName : parsedJson['name'],
studentScores : parsedJson ['score']
);
}
}
You create a new Student object like Student.fromJson(your_parsed_json).
Sub-objects work in a similar way. For each object inside the parent object you make a new Dart object, each with it's own parser for fromJson. Then inside the parent factory you call that fromJson method (like so)... This also works for lists of objects.
factory Student.fromJson(Map<String, dynamic> parsedJson){
return Student(
studentId: parsedJson['id'],
studentName : parsedJson['name'],
studentScores : Teacher.fromJson(parsedJson['teacher'])
);

Byte array and JSON in [FromBody]

I am trying pass an object which consists of different data type. I am always getting null value for orderDetails in Web API.
However if do this,
purchaseOrder.Attachments = null,
in the client then orderDetails is no longer null and I have other informations like "SendEmail" and PurchaseOrderNumber.
It looks I might not be correctly set the parameter in the client (angular 2).
However testing the same Web Api method from Console app works fine and I am not getting a null value.
Do I need to separate the JSON data and byte array?
regards,
-Alan-
Models
public class Attachments
{
public int AttachmentId { get; set; }
public string FileName { get; set ;}
public byte[] FileData { get; set ;}
}
public class UpdatePurchaseOrderViewModel
{
public bool SendEmail { get; set; }
public int PurchaseOrderNumber { get; set; }
public Attachments Attachments { get; set;
}
Here is my Web API put method definition
[HttpPut("AddPurchaseOrderNumber/{purchaseOrderId}")]
public StatusCodeResult AddPurchaseOrderNumber(int purchaseOrderId, [FromBody] UpdatePurchaseOrderViewModel orderDetails)
{
try
{
var status = _service.AddPurchaseOrderNumber(purchaseOrderId, orderDetails);
if (status == 200)
_unitOfWorkAsync.SaveChanges();
else return StatusCode(status);//No Data
}
catch
{
return StatusCode(400); // Bad Request
}
return StatusCode(200);//OK
}
Typescript snippet
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept','application/json');
let options = new RequestOptions({ headers: headers });
var body = JSON.stringify(
purchaseOrder
);
var uri = 'http://localhost:33907/api/purchaseorder/addpurchaseordernumber/' + purchaseOrderId;
return this._http.put(uri, body , options)
.map((response: Response) => {
let data = response.json();
if (data) {
return true;
}
else {
return false;
}
})
Update
The orderDetails is created as below
let file = Observable.create((observer) => {
let fr = new FileReader();
let data = new Blob([this.attachment]);
fr.readAsArrayBuffer(data);
fr.onloadend = () => {
observer.next(fr.result);
observer.complete();
};
fr.onerror = (err) => {
observer.error(err);
}
fr.onabort = () => {
observer.error("aborted");
}
});
file.map((fileData) => {
//build the attachment object which will be sent to Web API
let attachment: Attachments = {
AttachmentId: '0',
FileName: this.form.controls["attachmentName"].value,
FileData: fileData
}
//build the purchase order object
let order: UpdatePurchaseOrder = {
SendEmail: true,
PurchaseOrderNumber:this.form.controls["purchaseOrderNumber"].value * 1, //for casting purpose
Attachments: attachment
}
console.log("Loading completed");
return order;
})
When sending objects that have byte arrays as a property back and forth between a client to a WebAPI endpoint, I typically use a DTO that stores the property to explicitly define it as a Base64 string. On the server side I map the DTO to my entity by converting the Base64 string to / from the byte array for server side operations and storing in the database.
The serializer will do something like this automatically but the format passed from JavaScript may not match what the WebAPI JSON serializer is expecting (which is why it's working from your C# Console App).
You didn't include how you are creating the purchaseOrder object in your JavaScript so I can't comment on how that object is being setup - which may be where your issue is.

Resources